Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ func Parse(token *mTypes.Token) *mTypes.Program {

log.DebugMessage("code validating")
validateReference(prog.Declare.Func, prog.Declare.Func)
validateVarDeclare(prog.Declare.Func, prog.Declare.Func)
validateVarDeclare(prog.Declare.Func, prog.Declare.Func, map[string]bool{})
validateExtendedTypeReference(prog.Declare.Func, prog.Declare.Func)
log.DebugMessage("code validated")

Expand Down
29 changes: 23 additions & 6 deletions pkg/parser/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,29 @@ import (
mTypes "github.com/wf001/modo/pkg/types"
)

func validateVarDeclare(n *mTypes.Node, root *mTypes.Node) {
func validateVarDeclare(n *mTypes.Node, root *mTypes.Node, used map[string]bool) {
// To check for duplicate variable and type declarations, a Set would be appropriate,
// but since Go doesn't include one in the standard library,
// implement provisionally using a map to avoid extra dependencies.
if n == nil {
return
}

if n.Kind == mTypes.ND_TYPE_DECLARE {
used[n.Val] = true
return
}

if n.Kind == mTypes.ND_VAR_DECLARE {
if used[n.Val] {
log.Panic(
"%s: cannot use %s, already used",
error.ERROR_SYNTAX_ERROR,
n.Val,
)
}
used[n.Val] = true

if n.Child == nil {
log.Panic(
"%s: the value of '%s' not defined",
Expand All @@ -25,11 +38,9 @@ func validateVarDeclare(n *mTypes.Node, root *mTypes.Node) {

} else if n.Child.Type == nil {
// skip validating
validateVarDeclare(n.Child, root)

} else if n.Child.Kind == mTypes.ND_FUNCCALL {
// skip validating
validateVarDeclare(n.Child, root)

} else if n.Type.Value != n.Child.Type.Value {
log.Panic(
Expand All @@ -41,9 +52,15 @@ func validateVarDeclare(n *mTypes.Node, root *mTypes.Node) {
)
}
}
validateVarDeclare(n.Next, root)
validateVarDeclare(n.Child, root)
validateVarDeclare(n.Bind, root)
if n.Next != nil {
validateVarDeclare(n.Next, root, used)
}
if n.Child != nil {
validateVarDeclare(n.Child, root, used)
}
if n.Bind != nil {
validateVarDeclare(n.Bind, root, used)
}
}

func findDeclare(n *mTypes.Node, targetVal string) *mTypes.Node {
Expand Down
1 change: 1 addition & 0 deletions script/test-full.sh
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ testexec(){
assertexec '(def main ::int (fn [] (let [x ::int "hello"] (prn x))))' "level=error msg=\"syntax error: cannot use string type as x (int type)\""
assertexec '(def main ::int (fn [] (let [x ::bool "true"] (prn x))))' "level=error msg=\"syntax error: cannot use string type as x (bool type)\""
assertexec '(defschema Person {:name :: string :age :: int :isMale :: bool})(def main :: int (fn [] (let [node :: node {:age 20 :name "richard" :isMale true}] (prn (get node :name)) (prn (get node :age)) (prn (get node :isMale))))))' "level=error msg=\"syntax error: undefined type: node\""
assertexec '(def main ::int (fn [] (let [x ::int 1 x ::int 2] (prn x))))' "level=error msg=\"syntax error: cannot use x, already used\""
}

build-compiler
Expand Down