mirror of
https://github.com/Open-Argon/argon-v3.git
synced 2025-12-06 08:56:07 +00:00
rewrite variable.go to allow indexed asignment
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
180
src/variable.go
180
src/variable.go
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user