From 74aa33808dbe2630eb5fac427874428d55011267 Mon Sep 17 00:00:00 2001 From: Kyle Gunger Date: Sat, 9 Apr 2022 05:55:03 -0400 Subject: TINT v1 (PRE-ALPHA) + Added support for else/else if blocks + Fixed a bug with parsing string literals + Tested printing values to the cli + I think file writing/reading should work but it's a little hit or miss atm --- src/texec/eval.go | 99 ++++++++++++++++++++++++++++++++++++++++------------ src/texec/libtnsl.go | 35 ++++++++++--------- 2 files changed, 95 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/texec/eval.go b/src/texec/eval.go index 4d06ee1..f88c5e2 100644 --- a/src/texec/eval.go +++ b/src/texec/eval.go @@ -363,7 +363,7 @@ func getStringLiteral(v tparse.Node) []interface{} { out := []interface{}{} for i := 0; i < len(dat); i++ { - out = append(out, dat) + out = append(out, dat[i]) } return out @@ -601,12 +601,6 @@ func resolveArtifactCall(a TArtifact, params []TVariable) TVariable { } else { errOut("Need at least one arg to call tnsl.io func") } - } else if tres == 1 { - if len(params) > 1 { - return tnslFileEval(params[0], params[1], a.Name) - } else { - errOut("Not enough args recieved to call tnsl.io.File method.") - } } blk, pth := searchNode(a) @@ -625,6 +619,26 @@ func resolveArtifactCall(a TArtifact, params []TVariable) TVariable { } func resolveStructCall(a TArtifact, method string, params []TVariable) TVariable { + if len(a.Path) > 0 && a.Path[0] == "tnsl" { + a.Path = append(a.Path, a.Name) + a.Name = method + tres := tnslResolve(a) + + if a.Name == "close" { + params = append(params, null) + } + + if tres == 1 { + if len(params) > 1 { + return tnslFileEval(TVariable{tFile, *(params[0].Data.(*interface{}))}, params[1], a.Name) + } else { + errOut("Not enough args recieved to call tnsl.io.File method.") + } + } else { + return null + } + } + blk, pth := searchNode(a) if blk == nil { @@ -702,7 +716,7 @@ func evalCIN(v tparse.Node, ctx *VarMap, wk *TVariable) *TVariable { pth := wk.Type.T if wk != nil && wk.Data != nil { args = append(args, *wk) - } + } for i := 0; i < len(v.Sub[0].Sub); i++ { args = append(args, *evalValue(v.Sub[0].Sub[i], ctx)) @@ -909,17 +923,26 @@ func evalValue(v tparse.Node, ctx *VarMap) *TVariable { return &null } return &TVariable{ref.Type, *(ref.Data.(*interface{}))} - case "!": - a := convertVal(evalValue(v.Sub[0], ctx), tBool) - return &TVariable{tBool, !(a.Data.(bool))} - case "len": - a := evalValue(v.Sub[0], ctx) - return &TVariable{tInt, len(a.Data.([]interface{}))} - case "~": - a := evalValue(v.Sub[0], ctx) - typ := a.Type - typ.Pre = append([]string{"~"}, typ.Pre...) - return &TVariable{typ, &(a.Data)} + } + + if len(v.Sub) == 1 { + switch v.Data.Data { + case "!": + a := convertVal(evalValue(v.Sub[0], ctx), tBool) + return &TVariable{tBool, !(a.Data.(bool))} + case "len": + a := evalValue(v.Sub[0], ctx) + return &TVariable{tInt, len(a.Data.([]interface{}))} + case "~": + a := evalValue(v.Sub[0], ctx) + typ := a.Type + typ.Pre = append([]string{"~"}, typ.Pre...) + return &TVariable{typ, &(a.Data)} + case "-": + a := convertVal(evalValue(v.Sub[0], ctx), tFloat) + a.Data = -(a.Data.(float64)) + return a + } } // General case setup @@ -991,6 +1014,7 @@ func evalDef(v tparse.Node, ctx *VarMap) { func evalCF(v tparse.Node, ctx *VarMap) (bool, TVariable, int) { loop := true + ifout := true cond := tparse.Node{tparse.Token{tparse.LITERAL, "true", -1, -1}, []tparse.Node{}} var after *tparse.Node = nil @@ -999,7 +1023,7 @@ func evalCF(v tparse.Node, ctx *VarMap) (bool, TVariable, int) { for i := 0; i < len(v.Sub[0].Sub); i++ { switch v.Sub[0].Sub[i].Data.Data { - case "if": + case "if", "else": loop = false case "()": before = &(v.Sub[0].Sub[i]) @@ -1016,12 +1040,13 @@ func evalCF(v tparse.Node, ctx *VarMap) (bool, TVariable, int) { val := *evalValue(before.Sub[i].Sub[0], ctx) if i == len(before.Sub) - 1 && equateType(val.Type, tBool) { cond = before.Sub[i].Sub[0] + ifout = val.Data.(bool) } } } } - - for ; evalValue(cond, ctx).Data.(bool) ; { + + for ; (!loop && ifout) || evalValue(cond, ctx).Data.(bool) ; { for i := 0; i < len(v.Sub); i++ { switch v.Sub[i].Data.Data { case "define": @@ -1039,6 +1064,16 @@ func evalCF(v tparse.Node, ctx *VarMap) (bool, TVariable, int) { goto CONCF } else if brk > 0 { return false, null, brk - 1 + } else if equateType(val.Type, tIF) { + if val.Data.(bool) == true { + i++ + + for ;i < len(v.Sub) && getNames(v.Sub[i])[0] == "else"; i++ {} + + if i < len(v.Sub) { + i-- + } + } } case "return": if len(v.Sub[i].Sub) > 0 { @@ -1089,6 +1124,10 @@ func evalCF(v tparse.Node, ctx *VarMap) (bool, TVariable, int) { } } + if !loop { + return false, TVariable{tIF, ifout}, 0 + } + return false, null, 0 } @@ -1142,6 +1181,22 @@ func evalBlock(b tparse.Node, params []TVariable, method bool) TVariable { ret, val, _ := evalCF(b.Sub[i], &ctx) if ret { return *convertVal(&val, rty) + } else if equateType(val.Type, tIF) { + if val.Data.(bool) == true { + i++ + + for ;i < len(b.Sub) && b.Sub[i].Data.Data == "block"; { + if getNames(b.Sub[i])[0] == "else" { + i++ + } else { + break + } + } + + if i < len(b.Sub) { + i-- + } + } } case "return": return *convertVal(evalValue(b.Sub[i].Sub[0], &ctx), rty) diff --git a/src/texec/libtnsl.go b/src/texec/libtnsl.go index 6fe431b..0f02f32 100644 --- a/src/texec/libtnsl.go +++ b/src/texec/libtnsl.go @@ -56,6 +56,9 @@ var ( // used only in module definintion tEnum = TType{Pre: []string{}, T: TArtifact{Path: []string{}, Name: "enum"}, Post: ""} tStruct = TType{Pre: []string{}, T: TArtifact{Path: []string{}, Name: "struct"}, Post: ""} + + // Special types for if chain checking + tIF = TType{Pre: []string{}, T: TArtifact{Path: []string{}, Name: "if"}, Post: ""} ) // tells if the stub supports a function @@ -114,30 +117,28 @@ func tnslFileEval(file, in TVariable, function string) TVariable { // Generic IO funcs func tprint(in TVariable) { - if equateType(in.Type, tString) { - fmt.Print(in.Data.(string)) - } else if equateType(in.Type, tCharp) { - fmt.Print(in.Data.(rune)) - } else { - fmt.Print(in.Data) - } + fmt.Print(in.Data) } func tprintln(in TVariable) { - if equateType(in.Type, tString) { - fmt.Println(in.Data.(string)) - } else if equateType(in.Type, tCharp) { - fmt.Println(in.Data.(rune)) - } else { - fmt.Println(in.Data) + fmt.Println(in.Data) +} + +func datToString(dat interface{}) string { + out := []byte{} + in := dat.([]interface{}) + for i := 0; i < len(in); i++ { + out = append(out, in[i].(byte)) } + + return string(out) } func topenWriteFile(in TVariable) TVariable { - if equateType(in.Type, tString) { + if !equateType(in.Type, tString) { panic("Tried to open a file (for writing), but did not use a string type for the file name.") } - fd, err := os.Create(in.Data.(string)) + fd, err := os.Create(datToString(in.Data)) if err != nil { panic(fmt.Sprintf("Failed to open file (for writing) %v as requested by the program. Aborting.\n%v", in.Data, err)) } @@ -145,10 +146,10 @@ func topenWriteFile(in TVariable) TVariable { } func topenReadFile(in TVariable) TVariable { - if equateType(in.Type, tString) { + if !equateType(in.Type, tString) { panic("Tried to open a file (for reading), but did not use a string type for the file name.") } - fd, err := os.Open(in.Data.(string)) + fd, err := os.Open(datToString(in.Data)) if err != nil { panic(fmt.Sprintf("Failed to open file (for reading) %v as requested by the program. Aborting.\n%v", in.Data, err)) } -- cgit v1.2.3