diff --git a/pkg/codegen/codegen.go b/pkg/codegen/codegen.go index e8ab19f..d06031b 100644 --- a/pkg/codegen/codegen.go +++ b/pkg/codegen/codegen.go @@ -345,10 +345,11 @@ func (ctx *Context) genStructTypeDeclare(node *mTypes.Node) { for n := node.Child; n != nil; n = n.Next { // Note: is NOT TRUE rootTy, _, _ := mTypes.GetLLVMTypeRec(ctx.mod, n.Type, ctx.prog.Prelude) - // need to check others struct if rootTy == nil && n.IsType(mTypes.TY_EXTENDED) && n.Type.ExtendName == node.Val { + // check a self-reference rootTy = structType } else if rootTy == nil { + // check the reference to other struct rootTy = mTypes.GetExtendedType(ctx.prog.Declare, n).Types } f := structField[n.Val] diff --git a/pkg/codegen/prelude_prn.go b/pkg/codegen/prelude_prn.go index 29271a1..43542f7 100644 --- a/pkg/codegen/prelude_prn.go +++ b/pkg/codegen/prelude_prn.go @@ -142,10 +142,6 @@ func prnStructVector( nextIdx := loopBlock.NewAdd(loopIdx, mTypes.I64one) loopBlock.NewStore(nextIdx, loopIdxPtr) - condBlock.NewCall( - ctx.internal.Cstd.Printf, - ctx.internal.GlobalConst.StringComma, - ) condBlock.NewCall( ctx.internal.Cstd.Printf, ctx.internal.GlobalConst.StringSpace, diff --git a/pkg/lexer/lexer.go b/pkg/lexer/lexer.go index ca37341..0e007b4 100644 --- a/pkg/lexer/lexer.go +++ b/pkg/lexer/lexer.go @@ -4,6 +4,7 @@ import ( "regexp" "strings" + "github.com/wf001/modo/pkg/error" "github.com/wf001/modo/pkg/log" mTypes "github.com/wf001/modo/pkg/types" ) @@ -182,6 +183,9 @@ func doLexicalAnalyse(splittedString []string) *mTypes.Token { } } else { + if p == mTypes.SYMBOL_COMMA { + log.Panic("%s: can not use ',' as a symbol", error.ERROR_SYNTAX_ERROR) + } log.Debug("regard '%+v' as variable declaration or reference symbol", p) prev = newToken(mTypes.TK_IDENT, prev, p) } diff --git a/pkg/types/lex.go b/pkg/types/lex.go index 3ecb8f8..6749303 100644 --- a/pkg/types/lex.go +++ b/pkg/types/lex.go @@ -101,6 +101,8 @@ var ( PRELUDE_REDUCE, ) + SYMBOL_COMMA = "," + // Type signature SYMBOL_TYPE_SIG = "::" SYMBOL_TYPE_ARROW = "=>" @@ -144,6 +146,7 @@ var ( OPERATORS_REG_EXP, BRACKETS_REG_EXP, PRELUDE_PRN, + SYMBOL_COMMA, SYMBOL_UNDEFINED_REG_EXP, }, "|", diff --git a/script/test-full.sh b/script/test-full.sh index 418f04f..881eca3 100755 --- a/script/test-full.sh +++ b/script/test-full.sh @@ -250,30 +250,30 @@ testexec(){ echo "== vector ===" echo "===================" # local int - assertexec '(def main :: int (fn [] (let [vec :: [int] [41, 28, 239]] (prn vec))))' "[41, 28, 239]\\\n" + assertexec '(def main :: int (fn [] (let [vec :: [int] [41 28 239]] (prn vec))))' "[41 28 239]\\\n" # local string - assertexec '(def main :: int (fn [] (let [vec :: [string] ["Apple", "Banana"]] (prn vec))))' "[Apple, Banana]\\\n" + assertexec '(def main :: int (fn [] (let [vec :: [string] ["Apple" "Banana"]] (prn vec))))' "[Apple Banana]\\\n" # local bool - assertexec '(def main :: int (fn [] (let [vec :: [bool] [true, false, false, true]] (prn vec))))' "[true, false, false, true]\\\n" + assertexec '(def main :: int (fn [] (let [vec :: [bool] [true false false true]] (prn vec))))' "[true false false true]\\\n" # local double - assertexec '(def main :: int (fn [] (let [vec :: [double] [3.3 9.3]] (prn vec))))' "[3.3, 9.3]\\\n" + assertexec '(def main :: int (fn [] (let [vec :: [double] [3.3 9.3]] (prn vec))))' "[3.3 9.3]\\\n" # global int - assertexec '(def v :: [int] [233, 842]) (def main :: int (fn [] (prn v)))' "[233, 842]\\\n" + assertexec '(def v :: [int] [233 842]) (def main :: int (fn [] (prn v)))' "[233 842]\\\n" # global string - assertexec '(def v :: [string] ["Global", "Banana"]) (def main :: int (fn [] (prn v)))' "[Global, Banana]\\\n" + assertexec '(def v :: [string] ["Global" "Banana"]) (def main :: int (fn [] (prn v)))' "[Global Banana]\\\n" # global bool - assertexec '(def v :: [bool] [false, true, true]) (def main :: int (fn [] (prn v)))' "[false, true, true]\\\n" + assertexec '(def v :: [bool] [false true true]) (def main :: int (fn [] (prn v)))' "[false true true]\\\n" # taking args and returing - assertexec "(def f::[int] => nil (fn[v] (prn v))) (def main::int (fn[] (let[v::[int][42, 64, 90]] (f v))))" "[42, 64, 90]\\\n" - assertexec "(def f::[int] (fn[] (let[v::[int] [42, 64, 90, 84]]v))) (def main::int (fn[] (prn f)))" "[42, 64, 90, 84]\\\n" - assertexec "(def f :: [int] => [int] (fn [v] (conj v 81))) (def main :: int (fn [] (let [v :: [int] [42, 64, 90]] (prn (f v)))))" "[42, 64, 90, 81]\\\n" + assertexec "(def f::[int] => nil (fn[v] (prn v))) (def main::int (fn[] (let[v::[int][42 64 90]] (f v))))" "[42 64 90]\\\n" + assertexec "(def f::[int] (fn[] (let[v::[int] [42 64 90 84]]v))) (def main::int (fn[] (prn f)))" "[42 64 90 84]\\\n" + assertexec "(def f :: [int] => [int] (fn [v] (conj v 81))) (def main :: int (fn [] (let [v :: [int] [42 64 90]] (prn (f v)))))" "[42 64 90 81]\\\n" # 3-dimension assertexec "(def main :: int (fn [] (let [vec :: [[[int]]] [[[11 12 13] [14 15]] [[21 22 23] [24]] [[31 32] [33 34 35]] [[41 42] [43 44 45]]]] (prn (nth (nth (nth vec 1) 1) 0)) )))" "24\\\n" # reference - assertexec "(def main :: int (fn [] (let [vec1 :: [int] [42, 23] vec2 :: [int] vec1] (prn (conj vec2 1)) (prn (conj vec1 3)) (prn vec1) (prn vec2))))" "[42, 23, 1]\\\n[42, 23, 3]\\\n[42, 23]\\\n[42, 23]\\\n" + assertexec "(def main :: int (fn [] (let [vec1 :: [int] [42 23] vec2 :: [int] vec1] (prn (conj vec2 1)) (prn (conj vec1 3)) (prn vec1) (prn vec2))))" "[42 23 1]\\\n[42 23 3]\\\n[42 23]\\\n[42 23]\\\n" echo "===================" @@ -282,7 +282,7 @@ testexec(){ assertexec '(defschema Person {:name :: string :age :: int :isMale :: bool})(def main :: int (fn [] (let [node :: Person {:age 20 :name "richard" :isMale true}] (prn (get node :name)) (prn (get node :age)) (prn (get node :isMale))))))' "richard\\\n20\\\ntrue\\\n" assertexec '(defschema Person {:name :: string :age :: int :isMale :: bool :height :: double})(def main :: int (fn [] (let [node :: Person {:age 20 :name "richard" :isMale true :height 5.8}] (prn (get node :name)) (prn (get node :age)) (prn (get node :isMale)) (prn (get node :height))))))' "richard\\\n20\\\ntrue\\\n5.8\\\n" assertexec '(defschema Person {:name :: string :age :: int :isMale :: bool}) (def f :: Person (fn [] (let [node :: Person {:age 20 :name "richard" :isMale true}] node))) (def main :: int (fn [] (prn (get f :age))))' "20\\\n" - assertexec '(defschema Person {:name :: string :age :: int :isMale :: bool :height :: double :v :: [int]}) (def main :: int (fn [] (let [node :: Person {:age 20 :name "richard" :isMale true :height 5.8 :v [4, 3, 2]}] (prn (get node :name)) (prn (get node :age)) (prn (get node :isMale)) (prn (get node :height)) (prn (get node :v)) )))' "richard\\\n20\\\ntrue\\\n5.8\\\n[4, 3, 2]\\\n" + assertexec '(defschema Person {:name :: string :age :: int :isMale :: bool :height :: double :v :: [int]}) (def main :: int (fn [] (let [node :: Person {:age 20 :name "richard" :isMale true :height 5.8 :v [4 3 2]}] (prn (get node :name)) (prn (get node :age)) (prn (get node :isMale)) (prn (get node :height)) (prn (get node :v)) )))' "richard\\\n20\\\ntrue\\\n5.8\\\n[4 3 2]\\\n" assertexec '(defschema Person {:name ::string :next ::Person})(def main ::int (fn [] (let [node ::Person {:name "richard" :next {:name "rebecca" :next {:name "andre" :next {:name "bob"}}}}] (prn (get node :name)) (prn (get (get node :next) :name)) (prn (get (get (get node :next) :next) :name)) (prn (get (get (get (get node :next) :next) :next) :name)))))' "richard\\\nrebecca\\\nandre\\\nbob\\\n" assertexec '(defschema Country {:name ::string})(defschema Person {:name ::string :country ::Country})(def main ::int (fn [] (let [c ::Country {:name "deutsch"} person ::Person {:name "mike" :country c}] (prn (get (get person :country) :name)))))' "deutsch\\\n" @@ -304,16 +304,16 @@ testexec(){ echo "===================" echo "== map ===" echo "===================" - assertexec "(def inc :: int => int (fn [x] (+ x 1))) (def main :: int (fn [] (prn (map inc [32 13 99]))))" "[33, 14, 100]\\\n" - assertexec "(def inc :: double => double (fn [x] (+ x 1.3))) (def main :: int (fn [] (prn (map inc [4.2 1.8]))))" "[5.5, 3.1]\\\n" - assertexec '(def str :: int => string (fn [x] "a")) (def main :: int (fn [] (prn (map str [32 13 99]))))' "[a, a, a]\\\n" - assertexec '(def truely :: int => bool (fn [x] true)) (def main :: int (fn [] (prn (map truely [32 13 99]))))' "[true, true, true]\\\n" + assertexec "(def inc :: int => int (fn [x] (+ x 1))) (def main :: int (fn [] (prn (map inc [32 13 99]))))" "[33 14 100]\\\n" + assertexec "(def inc :: double => double (fn [x] (+ x 1.3))) (def main :: int (fn [] (prn (map inc [4.2 1.8]))))" "[5.5 3.1]\\\n" + assertexec '(def str :: int => string (fn [x] "a")) (def main :: int (fn [] (prn (map str [32 13 99]))))' "[a a a]\\\n" + assertexec '(def truely :: int => bool (fn [x] true)) (def main :: int (fn [] (prn (map truely [32 13 99]))))' "[true true true]\\\n" echo "===================" echo "== filter ===" echo "===================" - assertexec '(def even :: int => bool (fn [x] (= 0 (mod x 2)))) (def main :: int (fn [] (prn (filter even [8 1 7 10 18 42 45]))))' "[8, 10, 18, 42]\\\n" - assertexec '(def isThree :: int => bool (fn [x] (= 3 x))) (def main :: int (fn [] (prn (filter isThree [8 1 7 10 3 42 3]))))' "[3, 3]\\\n" + assertexec '(def even :: int => bool (fn [x] (= 0 (mod x 2)))) (def main :: int (fn [] (prn (filter even [8 1 7 10 18 42 45]))))' "[8 10 18 42]\\\n" + assertexec '(def isThree :: int => bool (fn [x] (= 3 x))) (def main :: int (fn [] (prn (filter isThree [8 1 7 10 3 42 3]))))' "[3 3]\\\n" assertexec '(def isThreeOne :: double => bool (fn [x] (= 3.1 x))) (def main :: int (fn [] (prn (filter isThreeOne [1.1 2.1 3.1]))))' "[3.1]\\\n" echo "===================" @@ -326,18 +326,18 @@ testexec(){ echo "== nth ===" echo "===================" # nth - assertexec '(def main :: int (fn [] (let [vec :: [int] [41, 28, 239]] (prn (nth vec 1)))))' "28\\\n" - assertexec '(def v :: [int] [233, 842]) (def main :: int (fn [] (prn (nth v 0))))' "233\\\n" - assertexec '(def main :: int (fn [] (let [vec :: [int] [423, 83, 90]] (prn (nth vec -1)) (prn (nth vec 2)) (prn (nth vec 3)) )))' "nil\\\n90\\\nnil\\\n" + assertexec '(def main :: int (fn [] (let [vec :: [int] [41 28 239]] (prn (nth vec 1)))))' "28\\\n" + assertexec '(def v :: [int] [233 842]) (def main :: int (fn [] (prn (nth v 0))))' "233\\\n" + assertexec '(def main :: int (fn [] (let [vec :: [int] [423 83 90]] (prn (nth vec -1)) (prn (nth vec 2)) (prn (nth vec 3)) )))' "nil\\\n90\\\nnil\\\n" echo "===================" echo "== conj ===" echo "===================" - assertexec '(def main :: int (fn [] (let [vec :: [int] [423, 83, 90]] (prn (conj vec 27)) (prn vec))))' "[423, 83, 90, 27]\\\n[423, 83, 90]\\\n" - assertexec '(def v :: [int] [233, 842]) (def main :: int (fn [] (prn (conj v 569))))' "[233, 842, 569]\\\n" - assertexec "(def v :: [int] [233, 842]) (def f :: [int] (fn [] (conj v 39))) (def main :: int (fn [] (prn f)))" "[233, 842, 39]\\\n" - assertexec '(def f::[int] => [int] (fn[v] (conj v 78))) (def main ::int (fn[] (let [v ::[int] [42, 64, 90]] (prn (f v)))))' "[42, 64, 90, 78]\\\n" - assertexec "(def main :: int (fn [] (let [vec :: [[int]] [[12, 34, 5, 6], [7,8,9]]] (prn (nth (conj vec [11, 12]) 2)) (prn (nth vec 2)))))" "[11, 12]\\\nnil\\\n" + assertexec '(def main :: int (fn [] (let [vec :: [int] [423 83 90]] (prn (conj vec 27)) (prn vec))))' "[423 83 90 27]\\\n[423 83 90]\\\n" + assertexec '(def v :: [int] [233 842]) (def main :: int (fn [] (prn (conj v 569))))' "[233 842 569]\\\n" + assertexec "(def v :: [int] [233 842]) (def f :: [int] (fn [] (conj v 39))) (def main :: int (fn [] (prn f)))" "[233 842 39]\\\n" + assertexec '(def f::[int] => [int] (fn[v] (conj v 78))) (def main ::int (fn[] (let [v ::[int] [42 64 90]] (prn (f v)))))' "[42 64 90 78]\\\n" + assertexec "(def main :: int (fn [] (let [vec :: [[int]] [[12 34 5 6] [789]]] (prn (nth (conj vec [11 12]) 2)) (prn (nth vec 2)))))" "[11 12]\\\nnil\\\n" # echo "===================" # echo "== assoc ===" diff --git a/script/test-lite.sh b/script/test-lite.sh index b3909da..f794e7f 100755 --- a/script/test-lite.sh +++ b/script/test-lite.sh @@ -14,11 +14,11 @@ testfile(){ echo "== fizzbuzz.modo ===" assertfile "fizzbuzz.modo" "1\\\n2\\\nFizz\\\n4\\\nBuzz\\\nFizz\\\n7\\\n8\\\nFizz\\\nBuzz\\\n11\\\nFizz\\\n13\\\n14\\\nFizzBuzz\\\n16\\\n17\\\nFizz\\\n19\\\n" echo "== vector_declare.modo ===" - assertfile "vector_declare.modo" "[233, 842]\\\n[Global, Banana]\\\n[42, 23]\\\n[Local, Apple]\\\n" + assertfile "vector_declare.modo" "[233 842]\\\n[Global Banana]\\\n[42 23]\\\n[Local Apple]\\\n" echo "== vector_operation.modo ===" - assertfile "vector_operation.modo" "54\\\n[423, 83, 90]\\\n" + assertfile "vector_operation.modo" "54\\\n[423 83 90]\\\n" echo "== vector_2d_li.modo ===" - assertfile "vector_2d_li.modo" "[7, 8, 9]\\\nnil\\\n" + assertfile "vector_2d_li.modo" "[789]\\\nnil\\\n" } diff --git a/script/testdata/vector_2d_li.modo b/script/testdata/vector_2d_li.modo index d0bb408..26de806 100644 --- a/script/testdata/vector_2d_li.modo +++ b/script/testdata/vector_2d_li.modo @@ -1,6 +1,6 @@ (def main :: int (fn [] - (let [vec :: [[int]] [[12, 34, 5, 6], [7,8,9]]] + (let [vec :: [[int]] [[12 34 5 6] [789]]] (prn (nth vec 1)) (prn (nth vec 2)) ))) diff --git a/script/testdata/vector_declare.modo b/script/testdata/vector_declare.modo index 933ebc0..5a7ee94 100644 --- a/script/testdata/vector_declare.modo +++ b/script/testdata/vector_declare.modo @@ -1,11 +1,11 @@ -(def vi :: [int] [233, 842]) -(def vs :: [string] ["Global", "Banana"]) +(def vi :: [int] [233 842]) +(def vs :: [string] ["Global" "Banana"]) (def main :: int (fn [] - (let [veci :: [int] [42, 23] - vecs :: [string] ["Local", "Apple"]] + (let [veci :: [int] [42 23] + vecs :: [string] ["Local" "Apple"]] (prn vi) (prn vs) (prn veci) diff --git a/script/testdata/vector_operation.modo b/script/testdata/vector_operation.modo index 3775e3b..9dba2c9 100644 --- a/script/testdata/vector_operation.modo +++ b/script/testdata/vector_operation.modo @@ -1,6 +1,6 @@ (def main :: int (fn [] - (let [vec :: [int] [423, 83, 90]] + (let [vec :: [int] [423 83 90]] (prn (nth (conj vec 54) 3))