add * import

This commit is contained in:
2023-07-10 22:18:02 +01:00
parent 88129528f4
commit 4d37d8d4de
9 changed files with 213 additions and 18 deletions

View File

@@ -620,6 +620,14 @@ func ArArray(arr []any) ArObject {
return true, ArErr{} return true, ArErr{}
}, },
} }
val.obj["copy"] = builtinFunc{
"copy",
func(args ...any) (any, ArErr) {
arrCopy := make([]any, len(arr))
copy(arrCopy, arr)
return ArArray(arrCopy), ArErr{}
},
}
val.obj["__Boolean__"] = builtinFunc{ val.obj["__Boolean__"] = builtinFunc{
"__Boolean__", "__Boolean__",
func(args ...any) (any, ArErr) { func(args ...any) (any, ArErr) {

View File

@@ -147,6 +147,7 @@ func ArWrite(args ...any) (any, ArErr) {
if typeof(args[0]) != "string" { if typeof(args[0]) != "string" {
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "text takes a string not type '" + typeof(args[0]) + "'", EXISTS: true} return ArObject{}, ArErr{TYPE: "Runtime Error", message: "text takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
} }
args[0] = ArValidToAny(args[0])
file.Write([]byte(args[0].(string))) file.Write([]byte(args[0].(string)))
return nil, ArErr{} return nil, ArErr{}
}}, }},

View File

@@ -36,10 +36,8 @@ func readFile(path string) []UNPARSEcode {
// optionally, resize scanner's capacity for lines over 64K, see next example // optionally, resize scanner's capacity for lines over 64K, see next example
output := []UNPARSEcode{} output := []UNPARSEcode{}
line := 1 line := 1
textOutput := []string{}
for scanner.Scan() { for scanner.Scan() {
text := scanner.Text() text := scanner.Text()
textOutput = append(textOutput, text)
output = append(output, UNPARSEcode{text, text, line, path}) output = append(output, UNPARSEcode{text, text, line, path})
line++ line++
} }

View File

@@ -115,8 +115,11 @@ func parseMap(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool,
} }
var mutex = sync.RWMutex{} var mutex = sync.RWMutex{}
var listenersMutex = sync.RWMutex{}
func Map(m anymap) ArObject { func Map(m anymap) ArObject {
var currentID uint32 = 0
listeners := map[any]map[uint32]any{}
obj := ArObject{ obj := ArObject{
obj: anymap{ obj: anymap{
"__value__": m, "__value__": m,
@@ -168,12 +171,29 @@ func Map(m anymap) ArObject {
return false, ArErr{} return false, ArErr{}
} }
mutex.RLock() mutex.RLock()
if _, ok := m[key]; !ok { if _, ok := m[key]; ok {
mutex.RUnlock() mutex.RUnlock()
return false, ArErr{} return true, ArErr{}
}
for k := range m {
compare, err := runOperation(
operationType{
operation: 9,
values: []any{key, k},
},
stack{},
0,
)
if err.EXISTS {
continue
}
if anyToBool(compare) {
mutex.RUnlock()
return true, ArErr{}
}
} }
mutex.RUnlock() mutex.RUnlock()
return true, ArErr{} return false, ArErr{}
}, },
}, },
"__NotContains__": builtinFunc{ "__NotContains__": builtinFunc{
@@ -191,12 +211,29 @@ func Map(m anymap) ArObject {
return true, ArErr{} return true, ArErr{}
} }
mutex.RLock() mutex.RLock()
if _, ok := m[key]; !ok { if _, ok := m[key]; ok {
mutex.RUnlock() mutex.RUnlock()
return true, ArErr{} return false, ArErr{}
}
for k := range m {
compare, err := runOperation(
operationType{
operation: 9,
values: []any{key, k},
},
stack{},
0,
)
if err.EXISTS {
continue
}
if anyToBool(compare) {
mutex.RUnlock()
return false, ArErr{}
}
} }
mutex.RUnlock() mutex.RUnlock()
return false, ArErr{} return true, ArErr{}
}, },
}, },
"__setindex__": builtinFunc{ "__setindex__": builtinFunc{
@@ -217,6 +254,20 @@ func Map(m anymap) ArObject {
} }
} }
key := ArValidToAny(args[0]) key := ArValidToAny(args[0])
listenersMutex.RLock()
if _, ok := listeners[key]; ok {
for _, v := range listeners[key] {
runCall(
call{
Callable: v,
Args: []any{args[1]},
},
stack{},
0,
)
}
}
listenersMutex.RUnlock()
mutex.Lock() mutex.Lock()
m[key] = args[1] m[key] = args[1]
mutex.Unlock() mutex.Unlock()
@@ -242,17 +293,33 @@ func Map(m anymap) ArObject {
} }
} }
mutex.RLock() mutex.RLock()
if _, ok := m[key]; !ok { if v, ok := m[key]; ok {
mutex.RUnlock() mutex.RUnlock()
return nil, ArErr{ return v, ArErr{}
TYPE: "KeyError", }
message: "key " + fmt.Sprint(key) + " not found", for k := range m {
EXISTS: true, compare, err := runOperation(
operationType{
operation: 9,
values: []any{key, k},
},
stack{},
0,
)
if err.EXISTS {
continue
}
if anyToBool(compare) {
mutex.RUnlock()
return m[k], ArErr{}
} }
} }
v := m[key]
mutex.RUnlock() mutex.RUnlock()
return v, ArErr{} return nil, ArErr{
TYPE: "KeyError",
message: "key " + fmt.Sprint(key) + " not found",
EXISTS: true,
}
}, },
}, },
}, },
@@ -299,6 +366,79 @@ func Map(m anymap) ArObject {
return true, ArErr{} return true, ArErr{}
}, },
} }
obj.obj["copy"] = builtinFunc{
"copy",
func(args ...any) (any, ArErr) {
debugPrintln("copy", args)
if len(args) != 0 {
return nil, ArErr{
TYPE: "TypeError",
message: "expected 0 arguments, got " + fmt.Sprint(len(args)),
EXISTS: true,
}
}
mutex.RLock()
newMap := make(anymap)
for k, v := range m {
newMap[k] = v
}
mutex.RUnlock()
return newMap, ArErr{}
},
}
obj.obj["addKeyChangeListener"] = builtinFunc{
"addKeyChangeListener",
func(args ...any) (any, ArErr) {
if len(args) != 2 {
return nil, ArErr{
TYPE: "TypeError",
message: "expected 2 arguments, got " + fmt.Sprint(len(args)),
EXISTS: true,
}
}
key := ArValidToAny(args[0])
if isUnhashable(key) {
return nil, ArErr{
TYPE: "Runtime Error",
message: "unhashable type: " + typeof(args[0]),
EXISTS: true,
}
}
if typeof(args[1]) != "function" {
return nil, ArErr{
TYPE: "TypeError",
message: "expected function, got " + typeof(args[1]),
EXISTS: true,
}
}
id := currentID
currentID++
listenersMutex.Lock()
if _, ok := listeners[key]; !ok {
listeners[key] = map[uint32]any{}
}
listeners[key][id] = args[1]
listenersMutex.Unlock()
return anymap{
"remove": builtinFunc{
"remove",
func(args ...any) (any, ArErr) {
if len(args) != 0 {
return nil, ArErr{
TYPE: "TypeError",
message: "expected 0 arguments, got " + fmt.Sprint(len(args)),
EXISTS: true,
}
}
listenersMutex.Lock()
delete(listeners[key], id)
listenersMutex.Unlock()
return nil, ArErr{}
},
},
}, ArErr{}
},
}
obj.obj["keys"] = builtinFunc{ obj.obj["keys"] = builtinFunc{
"keys", "keys",
func(args ...any) (any, ArErr) { func(args ...any) (any, ArErr) {

View File

@@ -6,7 +6,7 @@ import (
"strings" "strings"
) )
var numberCompile = makeRegex("( *)(-)?((([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)( *)") var numberCompile = makeRegex("( *)(-)?(((([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)|([0-9]+/[0-9]+))( *)")
var binaryCompile = makeRegex("( *)(-)?(0b[10]+(.\\[10]+)?(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)( *)") var binaryCompile = makeRegex("( *)(-)?(0b[10]+(.\\[10]+)?(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)( *)")
var hexCompile = makeRegex("( *)(-)?(0x[a-fA-F0-9]+(\\.[a-fA-F0-9]+)?)( *)") var hexCompile = makeRegex("( *)(-)?(0x[a-fA-F0-9]+(\\.[a-fA-F0-9]+)?)( *)")
var octalCompile = makeRegex("( *)(-)?(0o[0-7]+(\\.[0-7]+)?(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)( *)") var octalCompile = makeRegex("( *)(-)?(0o[0-7]+(\\.[0-7]+)?(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)( *)")

View File

@@ -781,7 +781,7 @@ func calcIntDiv(o operationType, stack stack, stacklevel int) (any, ArErr) {
return nil, err return nil, err
} }
if typeof(resp) == "number" && typeof(output) == "number" { if typeof(resp) == "number" && typeof(output) == "number" {
output = output.(number).Quo(output.(number), resp.(number)) output = floor(output.(number).Quo(output.(number), resp.(number)))
continue continue
} else if x, ok := output.(ArObject); ok { } else if x, ok := output.(ArObject); ok {
if y, ok := x.obj["__IntDivide__"]; ok { if y, ok := x.obj["__IntDivide__"]; ok {

View File

@@ -56,6 +56,8 @@ func parseGenericImport(code UNPARSEcode, index int, codeline []UNPARSEcode) (Ar
continue continue
} }
if after == "" { if after == "" {
} else if after == "*" {
asStr = true
} else if variableCompile.MatchString(after) { } else if variableCompile.MatchString(after) {
asStr = after asStr = after
} else { } else {
@@ -120,6 +122,27 @@ func runImport(importOBJ ArImport, stack stack, stacklevel int) (any, ArErr) {
} }
case string: case string:
builtinCall(setindex, []any{x, stackMap}) builtinCall(setindex, []any{x, stackMap})
case bool:
keyGetter, ok := stackMap.obj["keys"]
if !ok {
return nil, ArErr{"Import Error", "could not find keys in module scope", importOBJ.Line, importOBJ.Path, importOBJ.Code, true}
}
valueGetter, ok := stackMap.obj["__getindex__"]
if !ok {
return nil, ArErr{"Import Error", "could not find __getindex__ in module scope", importOBJ.Line, importOBJ.Path, importOBJ.Code, true}
}
keys, err := builtinCall(keyGetter, []any{})
if err.EXISTS {
return nil, err
}
keys = ArValidToAny(keys)
for _, v := range keys.([]any) {
val, err := builtinCall(valueGetter, []any{v})
if err.EXISTS {
return nil, err
}
builtinCall(setindex, []any{v, val})
}
} }
return nil, ArErr{} return nil, ArErr{}
} }

View File

@@ -73,4 +73,25 @@ var ArPath = Map(
EXISTS: true, EXISTS: true,
} }
}}, }},
"parent": builtinFunc{
"parent",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "runtime",
message: "parent takes exactly 1 argument, got " + fmt.Sprint(len(args)),
EXISTS: true,
}
}
args[0] = ArValidToAny(args[0])
if typeof(args[0]) != "string" {
return nil, ArErr{
TYPE: "runtime",
message: "parent argument must be a string, got " + typeof(args[0]),
EXISTS: true,
}
}
return path.Dir(args[0].(string)), ArErr{}
},
},
}) })

View File

@@ -216,11 +216,15 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
} }
if v.TYPE == "let" { if v.TYPE == "let" {
name := v.toset.(accessVariable).Name
if v.function {
resp = Callable{name, v.params, v.value, v.code, stack, v.line}
}
stackcallable, ok := stack[len(stack)-1].obj["__setindex__"] stackcallable, ok := stack[len(stack)-1].obj["__setindex__"]
if !ok { if !ok {
return nil, ArErr{"Type Error", "stack doesn't have __setindex__", v.line, v.path, v.code, true} return nil, ArErr{"Type Error", "stack doesn't have __setindex__", v.line, v.path, v.code, true}
} }
_, err := builtinCall(stackcallable, []any{v.toset.(accessVariable).Name, resp}) _, err := builtinCall(stackcallable, []any{name, resp})
if err.EXISTS { if err.EXISTS {
return nil, err return nil, err
} }