diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/texec/eval.go | 253 | ||||
| -rw-r--r-- | src/tparse/tree-statement.go | 6 | 
2 files changed, 168 insertions, 91 deletions
| diff --git a/src/texec/eval.go b/src/texec/eval.go index 4c1f9b4..4d06ee1 100644 --- a/src/texec/eval.go +++ b/src/texec/eval.go @@ -73,7 +73,7 @@ func errOutNode(msg string, n tparse.Node) {  	fmt.Println("==== BEGIN ERROR ====")  	fmt.Println(msg)  	fmt.Println(cart) -	fmt.Printf("Line: %v Char: %v", n.Data.Line, n.Data.Char) +	fmt.Printf("Line: %v Char: %v\n", n.Data.Line, n.Data.Char)  	fmt.Println("====  END  ERROR ====")  	panic(">>> PANIC FROM EVAL <<<")  } @@ -106,13 +106,12 @@ func getBlockName(block tparse.Node) []string {  			out = append(out, block.Sub[0].Sub[i].Sub[0].Data.Data)  		} else if block.Sub[0].Sub[i].Data.Type == tparse.KEYWORD {  			switch block.Sub[0].Sub[i].Data.Data { -			case "if", "elif", "else", "loop", "match", "case", "default": +			case "if", "else", "loop", "match", "case", "default":  				out = append(out, block.Sub[0].Sub[i].Data.Data)  			default:  			}  		}  	} -	fmt.Println(out)  	return out  } @@ -213,7 +212,9 @@ func getDef(mod *TModule, n string) *TVariable {  // Yes, I am aware that the following code is bad.  // No, I don't care. -func searchNode(s TArtifact) *tparse.Node { +// The first variable it returns represents the block if one was found +// The second node represents the absolute path to the block +func searchNode(s TArtifact) (*tparse.Node, TArtifact) {  	// i-- because we are doing a reverse lookup  	for i := len(cart.Path); i >= 0; i-- { // O(n) @@ -227,11 +228,14 @@ func searchNode(s TArtifact) *tparse.Node {  		ret := getNode(tst, s.Name) // O(n^2) (O(n^3) total here)  		if ret != nil { -			return ret +			pth := []string{} +			pth = append(pth, cart.Path[:i]...) +			pth = append(pth, s.Path...) +			return ret, TArtifact{ pth , s.Name }  		}  	} // Block total complexity 3*O(n^2) * O(n) = 3*O(n^3) -	return nil +	return nil, tNull.T  }  func searchDef(s TArtifact) *TVariable { @@ -532,13 +536,16 @@ func csts(st TArtifact, dat VarMap) VarMap {  }  func convertValPS(to TType, sk int, dat interface{}) interface{} { +	if isPointer(to, sk) || equateTypePSO(to, tFile, sk) { +		return dat +	} +  	var numcv float64  	switch v := dat.(type) {  	case []interface{}:  		if isArray(to, sk) {  			return cata(to.T, v)  		} else if isStruct(to, sk) { -			fmt.Println(to)  			return cvsa(to.T, v)  		}  	case VarMap: @@ -602,8 +609,39 @@ func resolveArtifactCall(a TArtifact, params []TVariable) TVariable {  		}  	} +	blk, pth := searchNode(a) + +	if blk == nil { +		errOut(fmt.Sprintf("Invalid call to %v", a)) +	} + +	// Store and restore the path to the block +	ocrt := cart +	cart = pth +	out := evalBlock(*blk, params, false) +	cart = ocrt +	return out +} + +func resolveStructCall(a TArtifact, method string, params []TVariable) TVariable { +	blk, pth := searchNode(a) + +	if blk == nil { +		errOut(fmt.Sprintf("Could not find a method block for given type %v", a)) +	} + +	for i := 0; i < len(blk.Sub); i++ { +		if getBlockName(blk.Sub[i])[0] == method { +			ocrt := cart +			cart = pth +			out := evalBlock(blk.Sub[i], params, true) +			cart = ocrt +			return out +		} +	} +	errOut(fmt.Sprintf("Could not find method %s in type %v", method, a))  	return null  } @@ -656,47 +694,41 @@ func isArray(t TType, skp int) bool {  	return t.Pre[skp] == "{}"  } -func evalIndex(n tparse.Node, v *TVariable) *interface{} { -	var out *interface{} = &(v.Data) - -	for i := 0; i < len(n.Sub); i++ { -		if n.Sub[i].Data.Data == "index" { -			out = &((*out).([]interface{})[getIntLiteral(n.Sub[i].Sub[0])]) -		} else { -			break -		} -	} - -	return out -} -  // Deals with call and index nodes  func evalCIN(v tparse.Node, ctx *VarMap, wk *TVariable) *TVariable {  	if v.Sub[0].Data.Data == "call" { -		pth := TArtifact{[]string{}, v.Data.Data} -		 -		if wk != nil { -			pth.Path = append(wk.Type.T.Path, wk.Type.T.Name) -		} -		  		args := []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))  		} -		// Make call somehow and properly set wk +		var tmp TVariable + +		if wk != nil && wk.Data != nil { +			tmp = resolveStructCall(pth, v.Data.Data, args) +		} else { +			tmp = resolveArtifactCall(pth, args) +		} +		 +		wk = &TVariable{tmp.Type, &(tmp.Data)} +  	} else {  		if wk == nil {  			tmp, prs := (*ctx)[v.Data.Data]  			if !prs { -				return nil +				errOutNode("Unable to find variable", v)  			}  			wk = &TVariable{tmp.Type, &(tmp.Data)}  		} else {  			tmp, prs := (*(wk.Data.(*interface{}))).(VarMap)[v.Data.Data]  			if !prs { -				return nil +				errOutNode("Unable to find struct variable (index)", v)  			}  			wk = &TVariable{tmp.Type, &(tmp.Data)}  		} @@ -706,10 +738,12 @@ func evalCIN(v tparse.Node, ctx *VarMap, wk *TVariable) *TVariable {  		switch v.Sub[i].Data.Data {  		case "index":  			ind := convertVal(evalValue(v.Sub[i].Sub[0], ctx), tInt).Data.(int) -			wk.Data = &((*(wk.Data.(*interface{}))).([]interface{}))[ind] +			wk.Data = &(((*(wk.Data.(*interface{}))).([]interface{}))[ind]) +			wk.Type.Pre = wk.Type.Pre[1:]  		case "`":  			// De-reference -			wk.Data = *((*(wk.Data.(*interface{}))).(*interface{})) +			wk.Data = (*(wk.Data.(*interface{}))) +			wk.Type.Pre = wk.Type.Pre[1:]  		}  	} @@ -717,8 +751,72 @@ func evalCIN(v tparse.Node, ctx *VarMap, wk *TVariable) *TVariable {  }  func evalDotChain(v tparse.Node, ctx *VarMap) *TVariable { +	out, prs := (*ctx)[v.Sub[0].Data.Data] +	wnd := &(v.Sub[0]) -	return nil +	if v.Sub[0].Data.Data == "self" && !prs { +		errOutNode("Use of 'self' keyword outside of method block.", v) +	} else if !prs { +		out = nil +	} else { +		if wnd.Data.Data != "self" { +			out = &TVariable{out.Type, &(out.Data)} +		} + +		if len(v.Sub[0].Sub) > 0 { +			out = evalCIN(v.Sub[0], ctx, out) +		} + +		v = v.Sub[1] +		if v.Data.Data == "." { +			wnd = &(v.Sub[0]) +		} else { +			wnd = &v +		} +	} + +	wrk := TArtifact{[]string{}, ""} + +	for ;; { +		if out == nil { +			if wrk.Name != "" { +				wrk.Path = append(wrk.Path, wrk.Name) +			} +			wrk.Name = wnd.Data.Data + +			tmp := searchDef(wrk) +			if tmp != nil { +				out = &TVariable{tmp.Type, &(tmp.Data)} +			} +		} + +		if len(wnd.Sub) > 0 { +				if out == nil { +					out = evalCIN(*wnd, ctx, &TVariable{TType{[]string{}, wrk, ""}, nil}) +				} else { +					out = evalCIN(*wnd, ctx, out) +				} +		} else if out != nil { +			tmp, prs := (*(out.Data.(*interface{}))).(VarMap)[wnd.Data.Data] +			if !prs { +				errOutNode("Unable to find struct variable (dot)", v) +			} +			out = &TVariable{tmp.Type, &(tmp.Data)} +		} + +		if v.Data.Data == "." { +			v = v.Sub[1] +			if v.Data.Data == "." { +				wnd = &(v.Sub[0]) +			} else { +				wnd = &v +			} +		} else { +			break +		} +	} + +	return out  }  func setVal(v tparse.Node, ctx *VarMap, val *TVariable) *TVariable { @@ -734,59 +832,29 @@ func setVal(v tparse.Node, ctx *VarMap, val *TVariable) *TVariable {  		for ;v.Data.Data == "."; {  			v = v.Sub[1]  		} -	} - +	} else { +		tmp, prs := (*ctx)[v.Data.Data] +		if !prs { +			errOutCTX("Unable to set a variable due to the variable not existing.", ctx) +		} -	if len(v.Sub) > 0 { -		if v.Sub[len(v.Sub) - 1].Data.Data == "++" { +		wrk = &TVariable{tmp.Type, &(tmp.Data)} -		} else if v.Sub[len(v.Sub) - 1].Data.Data == "--" { -			//*()convertVal() +		if len(v.Sub) > 0 { +			wrk = evalCIN(v, ctx, nil)  		}  	} -	art := TArtifact{[]string{}, v.Data.Data} -	wrk := resolveArtifact(art, ctx) -	vwk := v -	if v.Data.Data == "." { -		art.Name = v.Sub[0].Data.Data -		vwk = v.Sub[0] -		wrk = resolveArtifact(art, ctx) -		for ;wrk == nil; { -			art.Path = append(art.Path, art.Name) -			v = v.Sub[1] -			if v.Data.Data == "." { -				art.Name = v.Sub[0].Data.Data -				vwk = v.Sub[0] -				wrk = resolveArtifact(art, ctx) -			} else { -				art.Name = v.Data.Data -				wrk = resolveArtifact(art, ctx) -				break -			} +	if len(v.Sub) > 0 { +		if v.Sub[len(v.Sub) - 1].Data.Data == "++" { +			val = &TVariable{tFloat, convertValPS(tFloat, 0, *(wrk.Data.(*interface{}))).(float64) + 1} +		} else if v.Sub[len(v.Sub) - 1].Data.Data == "--" { +			val = &TVariable{tFloat, convertValPS(tFloat, 0, *(wrk.Data.(*interface{}))).(float64) - 1}  		}  	} -	 -	if wrk == nil { -		errOutCTX(fmt.Sprintf("Unable to set variable %s due to the variable not existing.", art), ctx) -	} - -	var set *interface{} = &(wrk.Data) -	 -	for ;; { -		if len(vwk.Sub) > 0 { -			 -		} -		if v.Data.Data == "." { -			vwk = v.Sub[0] - -			continue -		} - -		break -	} +	var set *interface{} = wrk.Data.(*interface{})  	(*set) = convertValPS((*wrk).Type, 0, val.Data) @@ -810,6 +878,13 @@ func evalValue(v tparse.Node, ctx *VarMap) *TVariable {  	switch v.Data.Type {  	case tparse.LITERAL: +		if v.Data.Data == "self" { +			s, prs := (*ctx)["self"] +			if !prs { +				errOutNode("Use of 'self' keyword when not in a method.", v) +			} +			return &TVariable{s.Type, *(s.Data.(*interface{}))} +		}  		t := getLiteralType(v)  		return &TVariable{t, getLiteral(v, t)}  	case tparse.DEFWORD: @@ -824,24 +899,27 @@ func evalValue(v tparse.Node, ctx *VarMap) *TVariable {  		return resolveArtifact(TArtifact{[]string{}, v.Data.Data}, ctx)  	case tparse.AUGMENT: -		// Special case for = -		if v.Data.Data == "=" { +		// Special cases +		switch v.Data.Data { +		case "=":  			return setVal(v.Sub[0], ctx, evalValue(v.Sub[1], ctx)) - -		} else if v.Data.Data == "." { +		case ".":  			ref := evalDotChain(v, ctx)  			if ref == nil {  				return &null  			}  			return &TVariable{ref.Type, *(ref.Data.(*interface{}))} - -		} else if v.Data.Data == "!" { - +		case "!":  			a := convertVal(evalValue(v.Sub[0], ctx), tBool)  			return &TVariable{tBool, !(a.Data.(bool))} -		} else if v.Data.Data == "len" { +		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)}  		}  		// General case setup @@ -1022,7 +1100,6 @@ func evalParams(pd tparse.Node, params *[]TVariable, ctx *VarMap, method bool) {  	pi := 0  	if method { -		(*ctx)["self"] = &(*params)[0]  		pi = 1  	} @@ -1041,6 +1118,10 @@ func evalBlock(b tparse.Node, params []TVariable, method bool) TVariable {  	var rty TType = tNull +	if method { +		ctx["self"] = &(params[0]) +	} +  	if b.Sub[0].Data.Data == "bdef" {  		for i := 0; i < len(b.Sub[0].Sub); i++ {  			if b.Sub[0].Sub[i].Data.Data == "[]" { diff --git a/src/tparse/tree-statement.go b/src/tparse/tree-statement.go index c88b102..cf25085 100644 --- a/src/tparse/tree-statement.go +++ b/src/tparse/tree-statement.go @@ -70,14 +70,10 @@ func parseBlock(tokens *[]Token, tok, max int) (Node, int) {  				def.Sub = append(def.Sub, tmp)  				tok += 1  			case "else": -				name = true -				sparse = true  				if (*tokens)[tok+1].Data == "if" { -					tmp.Data = Token{KEYWORD, "elif", t.Line, t.Char} -					def.Sub = append(def.Sub, tmp)  					tok++ -					continue  				} +				fallthrough  			case "if", "match", "case", "loop":  				name = true  				sparse = true |