diff --git a/pkg/codegen/codegen.go b/pkg/codegen/codegen.go index bdf5eef..7a3f322 100644 --- a/pkg/codegen/codegen.go +++ b/pkg/codegen/codegen.go @@ -178,6 +178,9 @@ func newStruct( ) value.Value { structCtx := mTypes.GetExtendedType(ctx.prog.Declare, node) + if structCtx == nil { + log.Panic("%s: not found type: have %+v", error.ERROR_UNDEFINE, node) + } // null pointer to struct: %struct* null nullStructPtr := constant.NewNull(types.NewPointer(structCtx.Types)) @@ -203,15 +206,20 @@ func newStruct( field := n value := n.Child - namePtr := ctx.block.NewGetElementPtr( + fieldPtr := ctx.block.NewGetElementPtr( structCtx.Types, structPtr, mTypes.I32zero, constant.NewInt(types.I32, int64(structCtx.Field[field.Val].Pos)), // name field ) v := ctx.gen(value) - ctx.block.NewStore(v, namePtr) + if _, ok := v.(*ir.InstBitCast); ok { + ctx.block.NewStore(nullStructPtr, fieldPtr) + ctx.block.NewStore(v, fieldPtr) + } else { + ctx.block.NewStore(v, fieldPtr) + } } return structPtr @@ -334,6 +342,10 @@ 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 { + rootTy = structType + } f := structField[n.Val] f.Pos = pos if _, ok := rootTy.(*types.StructType); ok { diff --git a/pkg/parser/parser.go b/pkg/parser/parser.go index 23ecb94..83d0e57 100644 --- a/pkg/parser/parser.go +++ b/pkg/parser/parser.go @@ -256,6 +256,9 @@ func parseDeclare(tok *mTypes.Token, parentKind mTypes.NodeKind) (*mTypes.Token, Val: structElmeName, Type: structElemType, } + if structTy.IsType(mTypes.TY_EXTENDED) { + structTy.Type.ExtendName = tok.Val + } child.Next = structTy child = child.Next tok = tok.Next @@ -489,6 +492,22 @@ func Parse(token *mTypes.Token) *mTypes.Program { updateReferenceToFunccall(d.Child, d, prog.Declare.Func) } + // add extendedName to the child node of var.reference that have TY_EXTENDED + walkNode(prog.Declare.Func, prog.Declare.Func, map[string]bool{}, + func(n *mTypes.Node, root *mTypes.Node, used map[string]bool) bool { + if n.IsKind(mTypes.ND_VAR_REFERENCE) && n.IsType(mTypes.TY_EXTENDED) { + decl := findTypeDeclare(root, n.Type.ExtendName) + if decl == nil { + log.Panic("%s: undefined type: %s", error.ERROR_SYNTAX_ERROR, n.Type.ExtendName) + } + if n.Child != nil { + n.Child.Type.ExtendName = n.Type.ExtendName + } + } + return true + }, + ) + prog.Debug(0) log.DebugMessage("code validating") diff --git a/pkg/types/node.go b/pkg/types/node.go index cd1c053..bb0be8f 100644 --- a/pkg/types/node.go +++ b/pkg/types/node.go @@ -110,7 +110,7 @@ func (node *Node) IsKind(kind NodeKind) bool { } func (node *Node) IsType(ty ModoType) bool { - return node.Type.Value == ty + return node.Type != nil && node.Type.Value == ty } func (node *Node) IsScalar() bool { diff --git a/script/test-full.sh b/script/test-full.sh index d89426b..86aedd1 100755 --- a/script/test-full.sh +++ b/script/test-full.sh @@ -283,6 +283,7 @@ testexec(){ 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 :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" ############# # Prelude functions