rewrite variable.go to allow indexed asignment

This commit is contained in:
2023-03-08 22:41:55 +00:00
parent f7603e30c4
commit 09deba8912
8 changed files with 166 additions and 42 deletions

View File

@@ -1,7 +1,6 @@
package main package main
type Callable struct { type Callable struct {
name string
params []string params []string
run any run any
code string code string

View File

@@ -99,7 +99,7 @@ func importMod(realpath string, origin string, main bool) ArErr {
return translationerr return translationerr
} }
global := scope{} global := scope{}
_, runimeErr, _, _ := run(translated, stack{vars, global}) _, runimeErr, _ := run(translated, stack{vars, global})
if runimeErr.EXISTS { if runimeErr.EXISTS {
return runimeErr return runimeErr
} }

View File

@@ -54,15 +54,14 @@ func runVal(line any, stack stack) (any, ArErr) {
} }
// returns error // returns error
func run(translated []any, stack stack) (any, ArErr, int, any) { func run(translated []any, stack stack) (any, ArErr, any) {
var output any = nil var output any = nil
count := 0
for _, val := range translated { for _, val := range translated {
val, err := runVal(val, stack) val, err := runVal(val, stack)
output = val output = val
if err.EXISTS { if err.EXISTS {
return nil, err, count, output return nil, err, output
} }
} }
return nil, ArErr{}, count, output return nil, ArErr{}, output
} }

View File

@@ -22,14 +22,15 @@ func shell() {
code := input("\x1b[38;5;240m>>> \x1b[0m\x1b[1;5;240m") code := input("\x1b[38;5;240m>>> \x1b[0m\x1b[1;5;240m")
fmt.Print("\x1b[0m") fmt.Print("\x1b[0m")
translated, translationerr := translate([]UNPARSEcode{{code, code, 1, "<shell>"}}) translated, translationerr := translate([]UNPARSEcode{{code, code, 1, "<shell>"}})
count := len(translated)
if translationerr.EXISTS { if translationerr.EXISTS {
panicErr(translationerr) panicErr(translationerr)
} }
_, runimeErr, count, output := run(translated, global) _, runimeErr, output := run(translated, global)
if runimeErr.EXISTS { if runimeErr.EXISTS {
panicErr(runimeErr) panicErr(runimeErr)
} }
if count == 0 { if count == 1 {
fmt.Println(anyToArgon(output, true, true, 3, 0, true, 1)) fmt.Println(anyToArgon(output, true, true, 3, 0, true, 1))
} }
} }

View File

@@ -94,7 +94,7 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, color b
if color { if color {
output = append(output, "\x1b[38;5;240m") output = append(output, "\x1b[38;5;240m")
} }
output = append(output, "<function "+x.name+">") output = append(output, "<function>")
if color { if color {
output = append(output, "\x1b[0m") output = append(output, "\x1b[0m")
} }

View File

@@ -26,12 +26,19 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine b
if worked { if worked {
return bracket, worked, err, step return bracket, worked, err, step
} }
} else if isSetVariable(code) { }
if isSetVariable(code) {
setvar, worked, err, step := parseSetVariable(code, index, codelines) setvar, worked, err, step := parseSetVariable(code, index, codelines)
if worked { if worked {
return setvar, worked, err, step return setvar, worked, err, step
} }
} }
if isAutoAsignVariable(code) {
setvar, worked, err, step := parseAutoAsignVariable(code, index, codelines)
if worked {
return setvar, worked, err, step
}
}
operation, worked, err, step := parseOperations(code, index, codelines) operation, worked, err, step := parseOperations(code, index, codelines)
if worked { if worked {
return operation, worked, err, step return operation, worked, err, step

View File

@@ -16,6 +16,8 @@ func typeof(val any) string {
return "function" return "function"
case ArMap: case ArMap:
return "map" return "map"
case accessVariable:
return "variable"
} }
return "unknown" return "unknown"
} }

View File

@@ -1,11 +1,15 @@
package main package main
import ( import (
"fmt"
"strings" "strings"
) )
var variableCompile = makeRegex(`( *)([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*( *)`) var variableCompile = makeRegex(`( *)([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*( *)`)
var setVariableCompile = makeRegex(`( *)(let( +))?([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*(\(( *)((([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*)(( *)\,( *)([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*)*)?( *)\))?( *)=(.|\n)+`) var validname = makeRegex(`(.|\n)+(\(( *)((([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*)(( *)\,( *)([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*)*)?( *)\))`)
var setVariableCompile = makeRegex(`( *)(let( +))(.|\n)+( *)=(.|\n)+`)
var autoAsignVariableCompile = makeRegex(`(.|\n)+=(.|\n)+`)
var deleteVariableCompile = makeRegex(`( *)delete( +)( *)`)
var blockedVariableNames = map[string]bool{ var blockedVariableNames = map[string]bool{
"if": true, "if": true,
@@ -20,6 +24,10 @@ var blockedVariableNames = map[string]bool{
"import": true, "import": true,
"from": true, "from": true,
"do": true, "do": true,
"true": true,
"false": true,
"null": true,
"delete": true,
} }
type accessVariable struct { type accessVariable struct {
@@ -31,7 +39,7 @@ type accessVariable struct {
type setVariable struct { type setVariable struct {
TYPE string TYPE string
name string toset any
value any value any
function bool function bool
params []string params []string
@@ -40,15 +48,17 @@ type setVariable struct {
path string path string
} }
type setFunction struct {
toset any
params []string
}
func isVariable(code UNPARSEcode) bool { func isVariable(code UNPARSEcode) bool {
return variableCompile.MatchString(code.code) return variableCompile.MatchString(code.code)
} }
func parseVariable(code UNPARSEcode) (accessVariable, bool, ArErr, int) { func parseVariable(code UNPARSEcode) (accessVariable, bool, ArErr, int) {
name := strings.TrimSpace(code.code) name := strings.TrimSpace(code.code)
if blockedVariableNames[name] {
return accessVariable{}, false, ArErr{"Naming Error", "Naming Error: \"" + name + "\" is a reserved keyword", code.line, code.path, code.realcode, true}, 1
}
return accessVariable{name: name, code: code.code, line: code.line, path: code.path}, true, ArErr{}, 1 return accessVariable{name: name, code: code.code, line: code.line, path: code.path}, true, ArErr{}, 1
} }
@@ -65,41 +75,106 @@ func isSetVariable(code UNPARSEcode) bool {
return setVariableCompile.MatchString(code.code) return setVariableCompile.MatchString(code.code)
} }
func isAutoAsignVariable(code UNPARSEcode) bool {
return autoAsignVariableCompile.MatchString(code.code)
}
func isDeleteVariable(code UNPARSEcode) bool {
return deleteVariableCompile.MatchString(code.code)
}
func nameToTranslated(code UNPARSEcode, index int, lines []UNPARSEcode) (any, bool, ArErr, int) {
if validname.MatchString(code.code) {
trimmed := strings.TrimSpace(code.code)
start := strings.LastIndex(trimmed, "(")
params := strings.Split(trimmed[start+1:len(trimmed)-1], ",")
for i := range params {
params[i] = strings.TrimSpace(params[i])
}
name := strings.TrimSpace(trimmed[:start])
fmt.Println(name)
if blockedVariableNames[name] {
fmt.Println(name)
return accessVariable{}, false, ArErr{"Naming Error", "\"" + name + "\" is a reserved keyword", code.line, code.path, code.realcode, true}, 1
}
value, success, err, i := translateVal(UNPARSEcode{
code: name,
realcode: code.realcode,
line: code.line,
path: code.path,
}, index, lines, false)
return setFunction{toset: value, params: params}, success, err, i
}
return translateVal(code, index, lines, false)
}
func parseSetVariable(code UNPARSEcode, index int, lines []UNPARSEcode) (setVariable, bool, ArErr, int) { func parseSetVariable(code UNPARSEcode, index int, lines []UNPARSEcode) (setVariable, bool, ArErr, int) {
trim := strings.TrimSpace(code.code) trim := strings.TrimSpace(code.code)
equalsplit := strings.SplitN(trim, "=", 2) equalsplit := strings.SplitN(trim, "=", 2)
spacesplit := strings.SplitN(equalsplit[0], " ", 2) spacesplit := strings.SplitN(equalsplit[0], " ", 2)
TYPE := "auto" name := strings.TrimSpace(spacesplit[1])
name := strings.TrimSpace(equalsplit[0])
params := []string{} params := []string{}
function := false function := false
if spacesplit[0] == "let" {
TYPE = "let"
name = strings.TrimSpace(spacesplit[1])
}
if name[len(name)-1] == ')' {
function = true
bracketsplit := strings.SplitN(name, "(", 2)
name = bracketsplit[0]
params = strings.Split(bracketsplit[1][:len(bracketsplit[1])-1], ",")
for i := 0; i < len(params); i++ {
params[i] = strings.TrimSpace(params[i])
}
}
if blockedVariableNames[name] { if blockedVariableNames[name] {
return setVariable{}, false, ArErr{"Naming Error", "Naming Error: \"" + name + "\" is a reserved keyword", code.line, code.path, code.realcode, true}, 1 return setVariable{}, false, ArErr{"Naming Error", "\"" + name + "\" is a reserved keyword", code.line, code.path, code.realcode, true}, 1
} }
value, success, err, i := translateVal(UNPARSEcode{code: equalsplit[1], realcode: code.realcode, line: code.line, path: code.path}, index, lines, true) toset, success, err, i := nameToTranslated(UNPARSEcode{code: name, realcode: code.realcode, line: code.line, path: code.path}, index, lines)
if err.EXISTS {
return setVariable{}, success, err, i
}
switch toset.(type) {
case accessVariable:
break
case setFunction:
function = true
params = toset.(setFunction).params
toset = toset.(setFunction).toset
default:
return setVariable{}, false, ArErr{"Type Error", "can't set for non variable, did you mean '=='?", code.line, code.path, code.realcode, true}, 1
}
value, success, err, i := translateVal(UNPARSEcode{code: equalsplit[1], realcode: code.realcode, line: code.line, path: code.path}, index, lines, false)
if !success { if !success {
return setVariable{}, false, err, i return setVariable{}, false, err, i
} }
return setVariable{TYPE: TYPE, name: name, value: value, function: function, params: params, line: code.line, code: code.code, path: code.path}, true, ArErr{}, i return setVariable{TYPE: "let", toset: toset, value: value, function: function, params: params, line: code.line, code: code.code, path: code.path}, true, ArErr{}, i
}
func parseAutoAsignVariable(code UNPARSEcode, index int, lines []UNPARSEcode) (setVariable, bool, ArErr, int) {
trim := strings.TrimSpace(code.code)
equalsplit := strings.SplitN(trim, "=", 2)
name := strings.TrimSpace(equalsplit[0])
params := []string{}
function := false
if blockedVariableNames[name] {
return setVariable{}, false, ArErr{"Naming Error", "\"" + name + "\" is a reserved keyword", code.line, code.path, code.realcode, true}, 1
}
toset, success, err, i := nameToTranslated(UNPARSEcode{code: name, realcode: code.realcode, line: code.line, path: code.path}, index, lines)
if err.EXISTS {
return setVariable{}, success, err, i
}
switch toset.(type) {
case accessVariable:
break
case ArMapGet:
break
case setFunction:
function = true
params = toset.(setFunction).params
toset = toset.(setFunction).toset
default:
return setVariable{}, false, ArErr{"Type Error", "can't set for non variable, did you mean '=='?", code.line, code.path, code.realcode, true}, 1
}
value, success, err, i := translateVal(UNPARSEcode{code: equalsplit[1], realcode: code.realcode, line: code.line, path: code.path}, index, lines, false)
if !success {
return setVariable{}, false, err, i
}
return setVariable{TYPE: "auto", toset: toset, value: value, function: function, params: params, line: code.line, code: code.code, path: code.path}, true, ArErr{}, i
} }
func setVariableValue(v setVariable, stack stack) (any, ArErr) { func setVariableValue(v setVariable, stack stack) (any, ArErr) {
var resp any var resp any
if v.function { if v.function {
resp = Callable{v.name, v.params, v.value, v.code, stack, v.line} resp = Callable{v.params, v.value, v.code, stack, v.line}
} else { } else {
respp, err := runVal(v.value, stack) respp, err := runVal(v.value, stack)
if err.EXISTS { if err.EXISTS {
@@ -107,19 +182,60 @@ func setVariableValue(v setVariable, stack stack) (any, ArErr) {
} }
resp = respp resp = respp
} }
if v.TYPE == "let" { if v.TYPE == "let" {
if _, ok := stack[len(stack)-1][v.name]; ok { if _, ok := stack[len(stack)-1][v.toset.(accessVariable).name]; ok {
return stack, ArErr{"Runtime Error", "variable \"" + v.name + "\" already exists", v.line, v.path, v.code, true} return stack, ArErr{"Runtime Error", "variable \"" + v.toset.(accessVariable).name + "\" already exists", v.line, v.path, v.code, true}
} }
stack[len(stack)-1][v.name] = resp stack[len(stack)-1][v.toset.(accessVariable).name] = resp
} else { } else {
for i := len(stack) - 1; i >= 0; i-- { switch x := v.toset.(type) {
if _, ok := stack[i][v.name]; ok { case accessVariable:
stack[i][v.name] = resp for i := len(stack) - 1; i >= 0; i-- {
return resp, ArErr{} if _, ok := stack[i][x.name]; ok {
stack[i][x.name] = resp
return resp, ArErr{}
}
}
stack[len(stack)-1][x.name] = resp
case ArMapGet:
respp, err := runVal(x.VAL, stack)
if err.EXISTS {
return nil, err
}
key, err := runVal(x.key, stack)
if err.EXISTS {
return nil, err
}
switch y := respp.(type) {
case ArMap:
y[key] = resp
default:
return nil, ArErr{"Runtime Error", "can't set for non map", v.line, v.path, v.code, true}
} }
} }
stack[len(stack)-1][v.name] = resp
} }
return resp, ArErr{} return resp, ArErr{}
} }
/*
func parseAutosAsignVariable(code UNPARSEcode, index int, lines []UNPARSEcode) (setVariable, bool, ArErr, int) {
trim := strings.TrimSpace(code.code)
equalsplit := strings.SplitN(trim, "=", 2)
name := strings.TrimSpace(equalsplit[0])
params := []string{}
function := false
if blockedVariableNames[name] {
return setVariable{}, false, ArErr{"Naming Error", "\"" + name + "\" is a reserved keyword", code.line, code.path, code.realcode, true}, 1
}
value, success, err, i := translateVal(UNPARSEcode{code: equalsplit[1], realcode: code.realcode, line: code.line, path: code.path}, index, lines, false)
if !success {
return setVariable{}, false, err, i
}
return setVariable{TYPE: "let", name: name, value: value, function: function, params: params, line: code.line, code: code.code, path: code.path}, true, ArErr{}, i
}
*/