make maps oop

This commit is contained in:
2023-04-08 15:34:15 +02:00
parent 90b506d22f
commit 2d3c7c42ce
31 changed files with 708 additions and 275 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
bin
array.json

46
app.py Normal file
View File

@@ -0,0 +1,46 @@
def interpret(code):
memory = {}
pointer = 0
code_ptr = 0
loops = []
while code_ptr < len(code):
command = code[code_ptr]
if command == '>':
pointer += 1
elif command == '<':
pointer -= 1
elif command == '+':
if pointer not in memory:
memory[pointer] = 0
memory[pointer] += 1
elif command == '-':
if pointer not in memory:
memory[pointer] = 0
memory[pointer] -= 1
elif command == '.':
print(chr(memory.get(pointer, 0)), end='')
elif command == ',':
memory[pointer] = ord(input())
elif command == '[':
if memory.get(pointer, 0) == 0:
loop_depth = 1
while loop_depth > 0:
code_ptr += 1
if code[code_ptr] == '[':
loop_depth += 1
elif code[code_ptr] == ']':
loop_depth -= 1
else:
loops.append(code_ptr)
elif command == ']':
if memory.get(pointer, 0) != 0:
code_ptr = loops[-1]
else:
loops.pop()
code_ptr += 1
# Example usage
interpret("++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.")
# Output: Hello World!

View File

@@ -12,17 +12,14 @@ let read(path) = do
char = line[j]
if (char == "," && not in_quotes) do
value = line[start:j].rightstrip("\r").strip()
if (value && value[0] == "\"" && value[-1] == "\"") do
value = value[1:value.length - 1]
if (value && value[0] == "\"" && value[-1] == "\"") value = value[1:value.length - 1]
value = value.replace("\"\"", "\"")
values.append(value)
start = j + 1
else if (char == "\"") do
in_quotes = not in_quotes
else if (char == "\"") in_quotes = not in_quotes
if (j == line.length - 1) do
value = line[start:j + 1].rightstrip("\r").strip()
if (value && value[0] == "\"" && value[-1] == "\"") do
value = value[1:value.length - 1]
if (value && value[0] == "\"" && value[-1] == "\"") value = value[1:value.length - 1]
value = value.replace("\"\"", "\"")
values.append(value)
data.append(values)

View File

@@ -20,8 +20,8 @@ func isArray(code UNPARSEcode) bool {
func ArArray(arr []any) ArObject {
val := ArObject{
"array",
anymap{
"__name__": "array",
"__value__": arr,
"length": newNumber().SetUint64(uint64(len(arr))),
},
@@ -39,7 +39,7 @@ func ArArray(arr []any) ArObject {
if typeof(a[0]) != "number" {
return nil, ArErr{
TYPE: "TypeError",
message: "index must be a number",
message: "dex must be a number",
EXISTS: true,
}
}
@@ -499,7 +499,6 @@ func ArArray(arr []any) ArObject {
}
output := []string{}
for _, v := range arr {
v = ArValidToAny(v)
if typeof(v) != "string" {
return nil, ArErr{
TYPE: "TypeError",
@@ -563,6 +562,31 @@ func ArArray(arr []any) ArObject {
}
return true, ArErr{}
}}
val.obj["__Contains__"] = builtinFunc{
"__Contains__",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "TypeError",
message: "missing argument",
EXISTS: true,
}
}
for _, v := range arr {
res, err := runOperation(operationType{
operation: 8,
values: []any{v, args[0]},
}, stack{}, 0)
if err.EXISTS {
return nil, err
}
if anyToBool(res) {
return true, ArErr{}
}
}
return false, ArErr{}
},
}
return val
}

View File

@@ -6,6 +6,8 @@ func AnyToArValid(arr any) any {
return ArArray(arr)
case string:
return ArString(arr)
case anymap:
return Map(arr)
default:
return arr
}
@@ -14,17 +16,9 @@ func AnyToArValid(arr any) any {
func ArValidToAny(a any) any {
switch a := a.(type) {
case ArObject:
switch a.TYPE {
case "string":
return a.obj["__value__"]
case "array":
return a.obj["__value__"]
case "class":
return a.obj["__value__"]
default:
return a.obj
if v, ok := a.obj["__value__"]; ok {
return v
}
default:
return a
}
return a
}

View File

@@ -13,7 +13,7 @@ func anyToBool(x any) bool {
case nil:
return false
case ArObject:
if x.TYPE == "array" {
if typeof(x) == "array" {
return len(x.obj["__value__"].([]any)) != 0
}
return len(x.obj) != 0

View File

@@ -1,23 +1,28 @@
package main
import (
"fmt"
"os"
)
func makeGlobal(allowDocument bool) ArObject {
var vars = Map(anymap{})
vars.obj["global"] = vars
var vars = anymap{}
vars["global"] = vars
vars["term"] = ArTerm
if allowDocument {
vars.obj["document"] = ArDocument
vars["document"] = ArDocument
}
vars.obj["js"] = ArJS
vars.obj["term"] = ArTerm
vars.obj["number"] = builtinFunc{"number", ArgonNumber}
vars.obj["string"] = builtinFunc{"string", ArgonString}
vars.obj["infinity"] = infinity
vars.obj["map"] = builtinFunc{"map", func(a ...any) (any, ArErr) {
vars["js"] = ArJS
vars["number"] = builtinFunc{"number", ArgonNumber}
vars["string"] = builtinFunc{"string", ArgonString}
vars["infinity"] = infinity
vars["map"] = builtinFunc{"map", func(a ...any) (any, ArErr) {
if len(a) == 0 {
return Map(anymap{}), ArErr{}
}
switch x := a[0].(type) {
case ArObject:
if x.TYPE == "array" {
if typeof(x) == "array" {
newmap := anymap{}
for i, v := range x.obj["__value__"].([]any) {
v := ArValidToAny(v)
@@ -35,7 +40,7 @@ func makeGlobal(allowDocument bool) ArObject {
newmap[i] = v
}
return Map(newmap), ArErr{}
} else if x.TYPE == "string" {
} else if typeof(x) == "string" {
newmap := anymap{}
for i, v := range x.obj["__value__"].(string) {
newmap[i] = ArString(string(v))
@@ -46,15 +51,15 @@ func makeGlobal(allowDocument bool) ArObject {
}
return nil, ArErr{TYPE: "TypeError", message: "Cannot create map from '" + typeof(a[0]) + "'", EXISTS: true}
}}
vars.obj["array"] = builtinFunc{"array", func(a ...any) (any, ArErr) {
vars["array"] = builtinFunc{"array", func(a ...any) (any, ArErr) {
if len(a) == 0 {
return ArArray([]any{}), ArErr{}
}
switch x := a[0].(type) {
case ArObject:
if x.TYPE == "array" {
if typeof(x) == "array" {
return x, ArErr{}
} else if x.TYPE == "string" {
} else if typeof(x) == "string" {
newarray := []any{}
for _, v := range x.obj["__value__"].(string) {
@@ -70,22 +75,22 @@ func makeGlobal(allowDocument bool) ArObject {
}
return nil, ArErr{TYPE: "TypeError", message: "Cannot create array from '" + typeof(a[0]) + "'", EXISTS: true}
}}
vars.obj["boolean"] = builtinFunc{"boolean", func(a ...any) (any, ArErr) {
vars["boolean"] = builtinFunc{"boolean", func(a ...any) (any, ArErr) {
if len(a) == 0 {
return false, ArErr{}
}
return anyToBool(a[0]), ArErr{}
}}
vars.obj["time"] = ArTime
vars.obj["PI"] = PI
vars.obj["π"] = PI
vars.obj["e"] = e
vars.obj["ln"] = builtinFunc{"ln", ArgonLn}
vars.obj["log"] = builtinFunc{"log", ArgonLog}
vars.obj["logN"] = builtinFunc{"logN", ArgonLogN}
vars.obj["thread"] = builtinFunc{"thread", ArThread}
vars.obj["input"] = ArInput
vars.obj["round"] = builtinFunc{"round", func(a ...any) (any, ArErr) {
vars["time"] = ArTime
vars["PI"] = PI
vars["π"] = PI
vars["e"] = e
vars["ln"] = builtinFunc{"ln", ArgonLn}
vars["log"] = builtinFunc{"log", ArgonLog}
vars["logN"] = builtinFunc{"logN", ArgonLogN}
vars["thread"] = builtinFunc{"thread", ArThread}
vars["input"] = ArInput
vars["round"] = builtinFunc{"round", func(a ...any) (any, ArErr) {
if len(a) == 0 {
return nil, ArErr{TYPE: "round", message: "round takes 1 argument",
EXISTS: true}
@@ -109,7 +114,7 @@ func makeGlobal(allowDocument bool) ArObject {
}
return nil, ArErr{TYPE: "TypeError", message: "Cannot round '" + typeof(a[0]) + "'", EXISTS: true}
}}
vars.obj["floor"] = builtinFunc{"floor", func(a ...any) (any, ArErr) {
vars["floor"] = builtinFunc{"floor", func(a ...any) (any, ArErr) {
if len(a) == 0 {
return nil, ArErr{TYPE: "floor", message: "floor takes 1 argument",
EXISTS: true}
@@ -120,7 +125,7 @@ func makeGlobal(allowDocument bool) ArObject {
}
return nil, ArErr{TYPE: "TypeError", message: "Cannot floor '" + typeof(a[0]) + "'", EXISTS: true}
}}
vars.obj["ceil"] = builtinFunc{"ceil", func(a ...any) (any, ArErr) {
vars["ceil"] = builtinFunc{"ceil", func(a ...any) (any, ArErr) {
if len(a) == 0 {
return nil, ArErr{TYPE: "ceil", message: "ceil takes 1 argument",
EXISTS: true}
@@ -132,26 +137,26 @@ func makeGlobal(allowDocument bool) ArObject {
}
return nil, ArErr{TYPE: "TypeError", message: "Cannot ceil '" + typeof(a[0]) + "'", EXISTS: true}
}}
vars.obj["sqrt"] = builtinFunc{"sqrt", ArgonSqrt}
vars.obj["file"] = ArFile
vars.obj["random"] = ArRandom
vars.obj["json"] = ArJSON
vars.obj["sin"] = ArSin
vars.obj["arcsin"] = ArArcsin
vars.obj["cos"] = ArCos
vars.obj["arccos"] = ArArccos
vars.obj["tan"] = ArTan
vars.obj["arctan"] = ArArctan
vars.obj["cosec"] = ArCosec
vars.obj["arccosec"] = ArArccosec
vars.obj["sec"] = ArSec
vars.obj["arcsec"] = ArArcsec
vars.obj["cot"] = ArCot
vars.obj["arccot"] = ArArccot
vars.obj["todeg"] = ArToDeg
vars.obj["torad"] = ArToRad
vars.obj["abs"] = ArAbs
vars.obj["dir"] = builtinFunc{"dir", func(a ...any) (any, ArErr) {
vars["sqrt"] = builtinFunc{"sqrt", ArgonSqrt}
vars["file"] = ArFile
vars["random"] = ArRandom
vars["json"] = ArJSON
vars["sin"] = ArSin
vars["arcsin"] = ArArcsin
vars["cos"] = ArCos
vars["arccos"] = ArArccos
vars["tan"] = ArTan
vars["arctan"] = ArArctan
vars["cosec"] = ArCosec
vars["arccosec"] = ArArccosec
vars["sec"] = ArSec
vars["arcsec"] = ArArcsec
vars["cot"] = ArCot
vars["arccot"] = ArArccot
vars["todeg"] = ArToDeg
vars["torad"] = ArToRad
vars["abs"] = ArAbs
vars["dir"] = builtinFunc{"dir", func(a ...any) (any, ArErr) {
if len(a) == 0 {
return ArArray([]any{}), ArErr{}
}
@@ -166,17 +171,17 @@ func makeGlobal(allowDocument bool) ArObject {
}
return ArArray([]any{}), ArErr{}
}}
vars.obj["subprocess"] = builtinFunc{"subprocess", ArSubprocess}
vars.obj["class"] = builtinFunc{"class", func(a ...any) (any, ArErr) {
vars["subprocess"] = builtinFunc{"subprocess", ArSubprocess}
vars["object"] = builtinFunc{"object", func(a ...any) (any, ArErr) {
if len(a) == 0 {
return nil, ArErr{TYPE: "TypeError", message: "Cannot create class from '" + typeof(a[0]) + "'", EXISTS: true}
}
switch x := a[0].(type) {
case ArObject:
if x.TYPE == "class" {
if typeof(x) == "object" {
return x, ArErr{}
}
newclass := ArObject{TYPE: "class", obj: anymap{}}
newclass := ArObject{obj: anymap{}}
for key, val := range x.obj {
newclass.obj[key] = val
}
@@ -184,5 +189,50 @@ func makeGlobal(allowDocument bool) ArObject {
}
return nil, ArErr{TYPE: "TypeError", message: "Cannot create class from '" + typeof(a[0]) + "'", EXISTS: true}
}}
return vars
vars["sequence"] = builtinFunc{"sequence", ArSequence}
vars["exit"] = builtinFunc{"exit", func(a ...any) (any, ArErr) {
if len(a) == 0 {
os.Exit(0)
}
switch x := a[0].(type) {
case number:
os.Exit(int(floor(x).Num().Int64()))
}
os.Exit(0)
return nil, ArErr{}
}}
vars["error"] = builtinFunc{"error", func(a ...any) (any, ArErr) {
if len(a) < 1 || len(a) > 2 {
return nil, ArErr{TYPE: "error", message: "error takes 1 or 2 arguments, got " + fmt.Sprint(len(a)), EXISTS: true}
}
if len(a) == 1 {
a[0] = ArValidToAny(a[0])
switch x := a[0].(type) {
case string:
return nil, ArErr{TYPE: "Error", message: x, EXISTS: true}
}
} else {
a[0] = ArValidToAny(a[0])
a[1] = ArValidToAny(a[1])
switch x := a[0].(type) {
case string:
switch y := a[1].(type) {
case string:
return nil, ArErr{TYPE: x, message: y, EXISTS: true}
}
}
}
return nil, ArErr{TYPE: "TypeError", message: "Cannot create error from '" + typeof(a[0]) + "'", EXISTS: true}
}}
vars["chr"] = builtinFunc{"chr", func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{TYPE: "chr", message: "chr takes 1 argument, got " + fmt.Sprint(len(a)), EXISTS: true}
}
switch x := a[0].(type) {
case number:
return string([]rune{rune(floor(x).Num().Int64())}), ArErr{}
}
return nil, ArErr{TYPE: "TypeError", message: "Cannot convert '" + typeof(a[0]) + "' to string", EXISTS: true}
}}
return Map(vars)
}

View File

@@ -16,6 +16,7 @@ type call struct {
}
type Callable struct {
name string
params []string
run any
code string
@@ -110,12 +111,33 @@ func runCall(c call, stack stack, stacklevel int) (any, ArErr) {
if len(x.params) != len(args) {
return nil, ArErr{"Runtime Error", "expected " + fmt.Sprint(len(x.params)) + " arguments, got " + fmt.Sprint(len(args)), c.line, c.path, c.code, true}
}
level := newscope()
l := anymap{}
for i, param := range x.params {
level.obj[param] = args[i]
l[param] = args[i]
}
resp, err := runVal(x.run, append(x.stack, level), stacklevel+1)
resp, err := runVal(x.run, append(x.stack, Map(l)), stacklevel+1)
return ThrowOnNonLoop(openReturn(resp), err)
}
return nil, ArErr{"Runtime Error", "type '" + typeof(callable) + "' is not callable", c.line, c.path, c.code, true}
}
func builtinCall(callable any, args []any) (any, ArErr) {
switch x := callable.(type) {
case builtinFunc:
resp, err := x.FUNC(args...)
resp = AnyToArValid(resp)
return resp, err
case Callable:
if len(x.params) != len(args) {
return nil, ArErr{TYPE: "Runtime Error", message: "expected " + fmt.Sprint(len(x.params)) + " arguments, got " + fmt.Sprint(len(args)), EXISTS: true}
}
level := newscope()
for i, param := range x.params {
level.obj[param] = args[i]
}
resp, err := runVal(x.run, append(x.stack, level), 0)
return ThrowOnNonLoop(openReturn(resp), err)
}
return nil, ArErr{TYPE: "Runtime Error", message: "type '" + typeof(callable) + "' is not callable", EXISTS: true}
}

View File

@@ -28,6 +28,7 @@ func ArRead(args ...any) (any, ArErr) {
if typeof(args[0]) != "string" {
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "read takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
}
args[0] = ArValidToAny(args[0])
filename := args[0].(string)
file, err := os.Open(filename)
if err != nil {
@@ -58,6 +59,7 @@ func ArWrite(args ...any) (any, ArErr) {
if typeof(args[0]) != "string" {
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "write takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
}
args[0] = ArValidToAny(args[0])
filename := args[0].(string)
file, err := os.Create(filename)
if err != nil {

View File

@@ -1,13 +1,11 @@
package main
import (
"fmt"
"strings"
)
type ArObject struct {
TYPE string
obj anymap
obj anymap
}
type anymap map[any]any
@@ -16,12 +14,11 @@ var mapGetCompile = makeRegex(`(.|\n)+\.([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(
var indexGetCompile = makeRegex(`(.|\n)+\[(.|\n)+\]( *)`)
type ArMapGet struct {
VAL any
args []any
index bool
line int
code string
path string
VAL any
args []any
line int
code string
path string
}
func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
@@ -31,57 +28,24 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
}
switch m := resp.(type) {
case ArObject:
if r.index && m.TYPE != "map" {
if _, ok := m.obj["__getindex__"]; ok {
callable := m.obj["__getindex__"]
resp, err := runCall(call{
callable: callable,
args: r.args,
line: r.line,
path: r.path,
code: r.code,
}, stack, stacklevel+1)
if !err.EXISTS {
return resp, ArErr{}
if _, ok := m.obj["__getindex__"]; ok {
callable := m.obj["__getindex__"]
resp, err := runCall(call{
callable: callable,
args: r.args,
line: r.line,
path: r.path,
code: r.code,
}, stack, stacklevel+1)
if !err.EXISTS {
return resp, ArErr{}
}
if len(r.args) == 1 && !isUnhashable(r.args[0]) {
if _, ok := m.obj[r.args[0]]; ok {
return m.obj[r.args[0]], ArErr{}
}
}
}
if len(r.args) > 1 {
return nil, ArErr{
"IndexError",
"index not found",
r.line,
r.path,
r.code,
true,
}
}
key, err := runVal(r.args[0], stack, stacklevel+1)
if err.EXISTS {
return nil, err
}
key = ArValidToAny(key)
if isUnhashable(key) {
return nil, ArErr{
"TypeError",
"unhashable type: '" + typeof(key) + "'",
r.line,
r.path,
r.code,
true,
}
}
if _, ok := m.obj[key]; !ok {
return nil, ArErr{
"KeyError",
"key '" + fmt.Sprint(key) + "' not found",
r.line,
r.path,
r.code,
true,
}
}
return AnyToArValid(m.obj[key]), ArErr{}
}
key, err := runVal(r.args[0], stack, stacklevel+1)
@@ -111,7 +75,7 @@ func mapGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapGet
if !worked {
return ArMapGet{}, false, err, i
}
return ArMapGet{resp, []any{key}, false, code.line, code.realcode, code.path}, true, ArErr{}, 1
return ArMapGet{resp, []any{key}, code.line, code.realcode, code.path}, true, ArErr{}, 1
}
func isIndexGet(code UNPARSEcode) bool {
@@ -149,7 +113,7 @@ func indexGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapG
}
continue
}
return ArMapGet{tival, args, true, code.line, code.realcode, code.path}, true, ArErr{}, 1
return ArMapGet{tival, args, code.line, code.realcode, code.path}, true, ArErr{}, 1
}
return ArMapGet{}, false, ArErr{
"Syntax Error",
@@ -161,7 +125,19 @@ func indexGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapG
}, 1
}
var hashabletypes = []string{
"number",
"string",
"bool",
"null",
}
func isUnhashable(val any) bool {
keytype := typeof(val)
return keytype == "array" || keytype == "map"
for _, v := range hashabletypes {
if v == keytype {
return false
}
}
return true
}

View File

@@ -41,8 +41,7 @@ func getPassword(args ...any) (string, error) {
char := make([]byte, 1)
_, err := os.Stdin.Read(char)
if err != nil {
fmt.Println(err)
break
return "", err
}
if char[0] == 3 || char[0] == 4 {
return "", fmt.Errorf("keyboard interupt")

View File

@@ -12,10 +12,7 @@ var Args = os.Args[1:]
type stack = []ArObject
func newscope() ArObject {
return ArObject{
TYPE: "map",
obj: make(anymap),
}
return Map(anymap{})
}
func main() {

View File

@@ -3,6 +3,7 @@ package main
import (
"fmt"
"strings"
"sync"
)
var mapCompiled = makeRegex(`( *)\{(((( *).+( *):( *).+( *))|(` + spacelessVariable + `))(( *)\,(( *).+( *):( *).+( *))|(` + spacelessVariable + `)))*\}( *)`)
@@ -25,16 +26,146 @@ func parseMap(code UNPARSEcode) (any, UNPARSEcode) {
return nil, UNPARSEcode{}
}
func Map(val anymap) ArObject {
func Map(m anymap) ArObject {
var mutex = sync.RWMutex{}
return ArObject{
TYPE: "map",
obj: val,
}
}
func Class(val anymap) ArObject {
return ArObject{
TYPE: "class",
obj: val,
obj: anymap{
"__value__": m,
"__name__": "map",
"get": builtinFunc{
"get",
func(args ...any) (any, ArErr) {
if len(args) < 1 || len(args) > 2 {
return nil, ArErr{
TYPE: "Runtime Error",
message: "expected 1 or 2 argument, got " + fmt.Sprint(len(args)),
EXISTS: true,
}
}
var DEFAULT any
key := ArValidToAny(args[0])
if isUnhashable(key) {
return nil, ArErr{
TYPE: "Runtime Error",
message: "unhashable type: " + typeof(key),
EXISTS: true,
}
}
if len(args) == 2 {
DEFAULT = (args[1])
}
mutex.RLock()
if _, ok := m[key]; !ok {
mutex.RUnlock()
return DEFAULT, ArErr{}
}
v := m[key]
mutex.RUnlock()
return v, ArErr{}
},
},
"__Contains__": builtinFunc{
"__Contains__",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "TypeError",
message: "expected 1 argument, got " + fmt.Sprint(len(args)),
EXISTS: true,
}
}
key := ArValidToAny(args[0])
if isUnhashable(key) {
return false, ArErr{}
}
mutex.RLock()
if _, ok := m[key]; !ok {
mutex.RUnlock()
return false, ArErr{}
}
mutex.RUnlock()
return true, ArErr{}
},
},
"__NotContains__": builtinFunc{
"__NotContains__",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "TypeError",
message: "expected 1 argument, got " + fmt.Sprint(len(args)),
EXISTS: true,
}
}
key := ArValidToAny(args[0])
if isUnhashable(key) {
return true, ArErr{}
}
mutex.RLock()
if _, ok := m[key]; !ok {
mutex.RUnlock()
return true, ArErr{}
}
mutex.RUnlock()
return false, ArErr{}
},
},
"__setindex__": builtinFunc{
"__setindex__",
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,
}
}
if isUnhashable(args[0]) {
return nil, ArErr{
TYPE: "Runtime Error",
message: "unhashable type: " + typeof(args[0]),
EXISTS: true,
}
}
key := ArValidToAny(args[0])
mutex.Lock()
m[key] = args[1]
mutex.Unlock()
return nil, ArErr{}
},
},
"__getindex__": builtinFunc{
"__getindex__",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "TypeError",
message: "expected 1 argument, got " + fmt.Sprint(len(args)),
EXISTS: true,
}
}
key := ArValidToAny(args[0])
if isUnhashable(key) {
return nil, ArErr{
TYPE: "Runtime Error",
message: "unhashable type: " + typeof(key),
EXISTS: true,
}
}
mutex.RLock()
if _, ok := m[key]; !ok {
mutex.RUnlock()
return nil, ArErr{
TYPE: "KeyError",
message: "key " + fmt.Sprint(key) + " not found",
EXISTS: true,
}
}
v := m[key]
mutex.RUnlock()
return v, ArErr{}
},
},
},
}
}

View File

@@ -557,12 +557,12 @@ func calcNotIn(o operationType, stack stack, stacklevel int) (any, ArErr) {
if err.EXISTS {
return false, err
}
if x, ok := resp.(ArObject); ok {
if x, ok := resp2.(ArObject); ok {
if y, ok := x.obj["__NotContains__"]; ok {
return runCall(
call{
y,
[]any{resp2},
[]any{resp},
o.code,
o.line,
o.path,
@@ -571,7 +571,7 @@ func calcNotIn(o operationType, stack stack, stacklevel int) (any, ArErr) {
}
return false, ArErr{
"Runtime Error",
"Cannot check if type '" + typeof(resp) + "' is in type '" + typeof(resp2) + "'",
"Cannot check if type '" + typeof(resp) + "' is not in type '" + typeof(resp2) + "'",
o.line,
o.path,
o.code,
@@ -697,7 +697,11 @@ func calcMod(o operationType, stack stack, stacklevel int) (any, ArErr) {
return nil, err
}
if typeof(resp) == "number" && typeof(output) == "number" {
output = floor(newNumber().Quo(resp.(number), output.(number)))
x := newNumber().Set(resp.(number))
x.Quo(output.(number), x)
x = floor(x)
x.Mul(x, resp.(number))
output.(number).Sub(output.(number), x)
continue
} else if x, ok := output.(ArObject); ok {
if y, ok := x.obj["__Modulo__"]; ok {

View File

@@ -0,0 +1,35 @@
package main
import "fmt"
func ArSequence(a ...any) (any, ArErr) {
if len(a) < 1 || len(a) > 2 {
return nil, ArErr{TYPE: "Runtime Error",
message: fmt.Sprintf("sequence expected 1 or 2 arguments, got %d", len(a)),
EXISTS: true,
}
}
f := a[0]
initial := newNumber()
if typeof(f) != "function" {
return nil, ArErr{TYPE: "Runtime Error",
message: fmt.Sprintf("sequence expected function, got %s", typeof(f)),
EXISTS: true,
}
}
if len(a) == 2 {
if typeof(a[1]) != "number" {
return nil, ArErr{TYPE: "Runtime Error",
message: fmt.Sprintf("sequence expected number, got %s", typeof(a[1])),
EXISTS: true,
}
}
initial.Set(a[1].(number))
}
return ArObject{
obj: map[any]any{
"__name__": "sequence",
"__value__": "test",
},
}, ArErr{}
}

View File

@@ -2,16 +2,16 @@ package main
import "fmt"
type keyCache map[interface{}]interface{}
type keyCache map[any]any
func quickSort(list []interface{}, getKey func(interface{}) (interface{}, ArErr)) ([]interface{}, ArErr) {
func quickSort(list []any, getKey func(any) (any, ArErr)) ([]any, ArErr) {
if len(list) <= 1 {
return list, ArErr{}
}
pivot := list[0]
var left []interface{}
var right []interface{}
var left []any
var right []any
var cache = make(keyCache)
@@ -51,7 +51,7 @@ func quickSort(list []interface{}, getKey func(interface{}) (interface{}, ArErr)
return append(append(left, pivot), right...), ArErr{}
}
func getkeyCache(getKey func(interface{}) (interface{}, ArErr), index interface{}, cache keyCache) (interface{}, ArErr) {
func getkeyCache(getKey func(any) (any, ArErr), index any, cache keyCache) (any, ArErr) {
key := ArValidToAny(index)
if cacheval, ok := cache[key]; ok {
return cacheval, ArErr{}

View File

@@ -47,9 +47,9 @@ func parseString(code UNPARSEcode) (string, bool, ArErr, int) {
func ArString(str string) ArObject {
obj := ArObject{
"string",
anymap{
"__value__": str,
"__name__": "string",
"length": newNumber().SetUint64(uint64(len(str))),
},
}
@@ -173,6 +173,7 @@ func ArString(str string) ArObject {
}
output := []string{str}
for _, v := range a {
v = ArValidToAny(v)
if typeof(v) != "string" {
return nil, ArErr{"TypeError", "expected string, got " + typeof(v), 0, "", "", true}
}
@@ -297,7 +298,9 @@ func ArString(str string) ArObject {
if typeof(a[1]) != "string" {
return nil, ArErr{"TypeError", "expected string, got " + typeof(a[1]), 0, "", "", true}
}
return strings.Replace(str, a[0].(ArObject).obj["__value__"].(string), a[1].(string), -1), ArErr{}
a[0] = ArValidToAny(a[0])
a[1] = ArValidToAny(a[1])
return strings.Replace(str, a[0].(string), a[1].(string), -1), ArErr{}
}}
obj.obj["contains"] = builtinFunc{
"contains",
@@ -494,7 +497,8 @@ func ArString(str string) ArObject {
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot get less than or equal to of type " + typeof(a[0]) + " from string", 0, "", "", true}
}
return str <= a[0].(ArObject).obj["__value__"].(string), ArErr{}
a[0] = ArValidToAny(a[0])
return str <= a[0].(string), ArErr{}
}}
obj.obj["__LessThan__"] = builtinFunc{
"__LessThan__",
@@ -505,7 +509,8 @@ func ArString(str string) ArObject {
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot get less than of type " + typeof(a[0]) + " from string", 0, "", "", true}
}
return str < a[0].(ArObject).obj["__value__"].(string), ArErr{}
a[0] = ArValidToAny(a[0])
return str < a[0].(string), ArErr{}
}}
obj.obj["__GreaterThan__"] = builtinFunc{
"__GreaterThan__",
@@ -516,7 +521,8 @@ func ArString(str string) ArObject {
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot get greater than of type " + typeof(a[0]) + " from string", 0, "", "", true}
}
return str > a[0].(ArObject).obj["__value__"].(string), ArErr{}
a[0] = ArValidToAny(a[0])
return str > a[0].(string), ArErr{}
}}
obj.obj["__GreaterThanEqual__"] = builtinFunc{
@@ -528,7 +534,8 @@ func ArString(str string) ArObject {
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot get greater than or equal to of type " + typeof(a[0]) + " from string", 0, "", "", true}
}
return str >= a[0].(ArObject).obj["__value__"].(string), ArErr{}
a[0] = ArValidToAny(a[0])
return str >= a[0].(string), ArErr{}
}}
obj.obj["__Equal__"] = builtinFunc{
"__Equal__",
@@ -536,6 +543,7 @@ func ArString(str string) ArObject {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
return str == a[0], ArErr{}
}}
obj.obj["__NotEqual__"] = builtinFunc{
@@ -544,6 +552,7 @@ func ArString(str string) ArObject {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
return str != a[0], ArErr{}
}}
obj.obj["__Add__"] = builtinFunc{
@@ -552,10 +561,11 @@ func ArString(str string) ArObject {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot add " + typeof(a[0]) + " to string", 0, "", "", true}
a[0] = anyToArgon(a[0], false, false, 3, 0, false, 0)
}
return strings.Join([]string{str, a[0].(ArObject).obj["__value__"].(string)}, ""), ArErr{}
return strings.Join([]string{str, a[0].(string)}, ""), ArErr{}
}}
obj.obj["__Multiply__"] = builtinFunc{
"__Multiply__",
@@ -584,7 +594,8 @@ func ArString(str string) ArObject {
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot check if string contains " + typeof(a[0]), 0, "", "", true}
}
return strings.Contains(str, a[0].(ArObject).obj["__value__"].(string)), ArErr{}
a[0] = ArValidToAny(a[0])
return strings.Contains(str, a[0].(string)), ArErr{}
}}
obj.obj["__Subtract__"] = builtinFunc{
"__Subtract__",
@@ -595,7 +606,8 @@ func ArString(str string) ArObject {
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot subtract " + typeof(a[0]) + " from string", 0, "", "", true}
}
return strings.Replace(str, a[0].(ArObject).obj["__value__"].(string), "", -1), ArErr{}
a[0] = ArValidToAny(a[0])
return strings.Replace(str, a[0].(string), "", -1), ArErr{}
}}
obj.obj["__Divide__"] = builtinFunc{
"__Divide__",
@@ -606,7 +618,8 @@ func ArString(str string) ArObject {
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot divide string by " + typeof(a[0]), 0, "", "", true}
}
splitby := a[0].(ArObject).obj["__value__"].(string)
a[0] = ArValidToAny(a[0])
splitby := a[0].(string)
output := []any{}
splitted := (strings.Split(str, splitby))
for _, v := range splitted {

View File

@@ -98,7 +98,7 @@ var ArTerm = Map(anymap{
"time": builtinFunc{"time", func(args ...any) (any, ArErr) {
var id any = nil
if len(args) > 0 {
id = args[0]
id = ArValidToAny(args[0])
}
timing[id] = time.Now()
return nil, ArErr{}
@@ -107,7 +107,7 @@ var ArTerm = Map(anymap{
"timeEnd": builtinFunc{"timeEnd", func(args ...any) (any, ArErr) {
var id any = nil
if len(args) > 0 {
id = args[0]
id = ArValidToAny(args[0])
}
if _, ok := timing[id]; !ok {
return nil, ArErr{TYPE: "TypeError", message: "Cannot find timer with id '" + fmt.Sprint(id) + "'", EXISTS: true}
@@ -131,8 +131,11 @@ var ArInput = Map(
}
return ArString(resp), ArErr{}
}},
"__call__": builtinFunc{"input", func(args ...any) (any, ArErr) {
return input(args...), ArErr{}
}},
},
)
func init() {
ArInput.obj["__call__"] = builtinFunc{"input", func(args ...any) (any, ArErr) {
return input(args...), ArErr{}
}}
}

View File

@@ -7,8 +7,7 @@ import (
var MicroSeconds = newNumber().SetInt64(1000000)
func ArTimeClass(N time.Time) ArObject {
return Class(anymap{
"__value__": newNumber().Quo(newNumber().SetInt64(N.UnixMicro()), MicroSeconds),
m := Map(anymap{
"year": builtinFunc{
"year",
func(a ...any) (any, ArErr) {
@@ -97,6 +96,8 @@ func ArTimeClass(N time.Time) ArObject {
},
},
})
m.obj["__value__"] = newNumber().Quo(newNumber().SetInt64(N.UnixMicro()), MicroSeconds)
return m
}
var ArTime = Map(anymap{
@@ -112,19 +113,43 @@ var ArTime = Map(anymap{
}},
"parse": builtinFunc{"parse", func(a ...any) (any, ArErr) {
if len(a) == 1 {
if typeof(a[0]) != "string" {
return nil, ArErr{
TYPE: "Runtime Error",
message: "parse requires a string",
EXISTS: true,
}
}
a[0] = ArValidToAny(a[0])
N, err := time.Parse(time.UnixDate, a[0].(string))
if err != nil {
return nil, ArErr{
TYPE: "ArErr",
TYPE: "Runtime Error",
message: err.Error(),
}
}
return ArTimeClass(N), ArErr{}
} else if len(a) > 1 {
if typeof(a[0]) != "string" {
return nil, ArErr{
TYPE: "Runtime Error",
message: "parse requires a string",
EXISTS: true,
}
}
a[0] = ArValidToAny(a[0])
if typeof(a[1]) != "string" {
return nil, ArErr{
TYPE: "Runtime Error",
message: "parse requires a string",
EXISTS: true,
}
}
a[1] = ArValidToAny(a[1])
N, err := time.Parse(a[0].(string), a[1].(string))
if err != nil {
return nil, ArErr{
TYPE: "ArErr",
TYPE: "Runtime Error",
message: err.Error(),
EXISTS: true,
}
@@ -132,17 +157,26 @@ var ArTime = Map(anymap{
return ArTimeClass(N), ArErr{}
}
return nil, ArErr{
TYPE: "ArErr",
message: "parse requires 2 arguments",
TYPE: "Runtime Error",
message: "parse requires 1 or 2 arguments",
EXISTS: true,
}
}},
"parseInLocation": builtinFunc{"parseInLocation", func(a ...any) (any, ArErr) {
if len(a) > 2 {
if len(a) != 2 {
if typeof(a[0]) != "string" || typeof(a[1]) != "string" {
return nil, ArErr{
TYPE: "Runtime Error",
message: "parseInLocation requires a string",
EXISTS: true,
}
}
a[0] = ArValidToAny(a[0])
a[1] = ArValidToAny(a[1])
N, err := time.ParseInLocation(a[0].(string), a[1].(string), time.Local)
if err != nil {
return nil, ArErr{
TYPE: "ArErr",
TYPE: "Runtime Error",
message: err.Error(),
EXISTS: true,
}
@@ -150,18 +184,26 @@ var ArTime = Map(anymap{
return ArTimeClass(N), ArErr{}
}
return nil, ArErr{
TYPE: "ArErr",
message: "parseInLocation requires 3 arguments",
TYPE: "Runtime Error",
message: "parseInLocation requires 2 arguments",
EXISTS: true,
}
},
},
"date": builtinFunc{"date", func(a ...any) (any, ArErr) {
if len(a) > 0 {
if len(a) != 1 {
if typeof(a[0]) != "string" {
return nil, ArErr{
TYPE: "Runtime Error",
message: "date requires a string",
EXISTS: true,
}
}
a[0] = ArValidToAny(a[0])
N, err := time.Parse(time.UnixDate, a[0].(string))
if err != nil {
return nil, ArErr{
TYPE: "ArErr",
TYPE: "Runtime Error",
message: err.Error(),
EXISTS: true,
}
@@ -169,45 +211,66 @@ var ArTime = Map(anymap{
return ArTimeClass(N), ArErr{}
}
return nil, ArErr{
TYPE: "ArErr",
TYPE: "Runtime Error",
message: "date requires 1 argument",
EXISTS: true,
}
},
},
"Unix": builtinFunc{"Unix", func(a ...any) (any, ArErr) {
if len(a) > 1 {
"unix": builtinFunc{"unix", func(a ...any) (any, ArErr) {
if len(a) != 2 {
if typeof(a[0]) != "number" || typeof(a[1]) != "number" {
return nil, ArErr{
TYPE: "Runtime Error",
message: "unix requires a number",
EXISTS: true,
}
}
sec, _ := a[0].(number).Float64()
nsec, _ := a[1].(number).Float64()
return ArTimeClass(time.Unix(int64(sec), int64(nsec))), ArErr{}
}
return nil, ArErr{
TYPE: "ArErr",
message: "Unix requires 2 arguments",
TYPE: "Runtime Error",
message: "unix requires 2 arguments",
EXISTS: true,
}
},
},
"UnixMilli": builtinFunc{"UnixMilli", func(a ...any) (any, ArErr) {
if len(a) > 0 {
"unixMilli": builtinFunc{"unixMilli", func(a ...any) (any, ArErr) {
if len(a) != 1 {
if typeof(a[0]) != "number" {
return nil, ArErr{
TYPE: "Runtime Error",
message: "unixMilli requires a number",
EXISTS: true,
}
}
msec, _ := a[0].(number).Float64()
return ArTimeClass(time.UnixMilli(int64(msec))), ArErr{}
}
return nil, ArErr{
TYPE: "ArErr",
TYPE: "Runtime Error",
message: "UnixMilli requires 1 argument",
EXISTS: true,
}
},
},
"UnixMicro": builtinFunc{"UnixMicro", func(a ...any) (any, ArErr) {
"unixMicro": builtinFunc{"unixMicro", func(a ...any) (any, ArErr) {
if len(a) > 0 {
if typeof(a[0]) != "number" {
return nil, ArErr{
TYPE: "Runtime Error",
message: "unixMicro requires a number",
EXISTS: true,
}
}
usec, _ := a[0].(number).Float64()
return ArTimeClass(time.UnixMicro(int64(usec))), ArErr{}
}
return nil, ArErr{
TYPE: "ArErr",
message: "UnixMicro requires 1 argument",
TYPE: "Runtime Error",
message: "unixMicro requires 1 argument",
EXISTS: true,
}
},

View File

@@ -3,6 +3,7 @@ package main
import (
"fmt"
"math"
"sort"
"strconv"
"strings"
@@ -78,6 +79,9 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
return "{}"
}
keys := make([]any, len(x))
sort.Slice(keys, func(i, j int) bool {
return anyToArgon(keys[i], false, true, 0, 0, false, 0) < anyToArgon(keys[j], false, true, 0, 0, false, 0)
})
i := 0
for k := range x {
@@ -148,7 +152,7 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
if colored {
output = append(output, "\x1b[38;5;240m")
}
output = append(output, "<function>")
output = append(output, "<function "+x.name+">")
if colored {
output = append(output, "\x1b[0m")
}

View File

@@ -103,6 +103,12 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i
return resp, worked, err, i
}
}
if isCall(code) {
resp, worked, err, i = parseCall(code, index, codelines)
if worked {
return resp, worked, err, i
}
}
{
operation, worked, err, step := parseOperations(code, index, codelines)
if worked {
@@ -113,16 +119,9 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i
}
if isNegative(code) {
return parseNegative(code, index, codelines)
} else if isCall(code) {
resp, worked, err, i = parseCall(code, index, codelines)
if worked {
return resp, worked, err, i
}
}
if isMapGet(code) {
} else if isMapGet(code) {
return mapGetParse(code, index, codelines)
}
if isIndexGet(code) {
} else if isIndexGet(code) {
resp, worked, err, i = indexGetParse(code, index, codelines)
if worked {
return resp, worked, err, i

View File

@@ -59,15 +59,15 @@ func parseTryCatch(code UNPARSEcode, index int, codelines []UNPARSEcode) (TryCat
func runTryCatch(t TryCatch, stack stack, stacklevel int) (any, ArErr) {
val, err := runVal(t.Try, stack, stacklevel)
if err.EXISTS {
scope := newscope()
scope.obj[t.errorName] = Map(anymap{
vars := anymap{}
vars[t.errorName] = Map(anymap{
"type": err.TYPE,
"message": err.message,
"line": newNumber().SetInt64(int64(err.line)),
"path": err.path,
"code": err.code,
})
val, err = runVal(t.Catch, append(stack, scope), stacklevel)
val, err = runVal(t.Catch, append(stack, Map(vars)), stacklevel)
if err.EXISTS {
return nil, err
}

View File

@@ -19,7 +19,13 @@ func typeof(val any) string {
case builtinFunc:
return "function"
case ArObject:
return x.TYPE
if val, ok := x.obj["__name__"]; ok {
val := ArValidToAny(val)
if val, ok := val.(string); ok {
return val
}
}
return "object"
case accessVariable:
return "variable"
}

View File

@@ -2,19 +2,16 @@ package main
import (
"strings"
"sync"
)
var spacelessVariable = `([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*`
var SpacelessVariableCompiled = makeRegex(spacelessVariable)
var variableCompile = makeRegex(`( *)([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*( *)`)
var variableCompile = makeRegex(`( *)` + spacelessVariable + `( *)`)
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( +)(.|\n)+( *)`)
var varMutex = sync.RWMutex{}
var blockedVariableNames = map[string]bool{
"if": true,
"else": true,
@@ -80,11 +77,20 @@ func parseVariable(code UNPARSEcode) (accessVariable, bool, ArErr, int) {
func readVariable(v accessVariable, stack stack) (any, ArErr) {
for i := len(stack) - 1; i >= 0; i-- {
varMutex.RLock()
val, ok := stack[i].obj[v.name]
varMutex.RUnlock()
if ok {
return val, ArErr{}
callable, ok := stack[i].obj["__Contains__"]
if !ok {
continue
}
contains, err := builtinCall(callable, []any{v.name})
if err.EXISTS {
return nil, err
}
if anyToBool(contains) {
callable, ok := stack[i].obj["__getindex__"]
if !ok {
continue
}
return builtinCall(callable, []any{v.name})
}
}
return nil, ArErr{"Name Error", "variable \"" + v.name + "\" does not exist", v.line, v.path, v.code, true}
@@ -200,7 +206,7 @@ func parseAutoAsignVariable(code UNPARSEcode, index int, lines []UNPARSEcode, is
func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
var resp any
if v.function {
resp = Callable{v.params, v.value, v.code, stack, v.line}
resp = Callable{"anonymous", v.params, v.value, v.code, stack, v.line}
} else {
respp, err := runVal(v.value, stack, stacklevel+1)
if err.EXISTS {
@@ -210,32 +216,48 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
}
if v.TYPE == "let" {
varMutex.RLock()
_, ok := stack[len(stack)-1].obj[v.toset.(accessVariable).name]
varMutex.RUnlock()
if ok {
return nil, ArErr{"Name Error", "variable \"" + v.toset.(accessVariable).name + "\" already exists", v.line, v.path, v.code, true}
stackcallable, ok := stack[len(stack)-1].obj["__setindex__"]
if !ok {
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})
if err.EXISTS {
return nil, err
}
varMutex.Lock()
stack[len(stack)-1].obj[v.toset.(accessVariable).name] = resp
varMutex.Unlock()
} else {
switch x := v.toset.(type) {
case accessVariable:
name := x.name
hasSet := false
if v.function {
resp = Callable{name, v.params, v.value, v.code, stack, v.line}
}
for i := len(stack) - 1; i >= 0; i-- {
varMutex.RLock()
_, ok := stack[i].obj[x.name]
varMutex.RUnlock()
if ok {
varMutex.Lock()
stack[i].obj[x.name] = resp
varMutex.Unlock()
return ThrowOnNonLoop(resp, ArErr{})
callable, ok := stack[i].obj["__Contains__"]
if !ok {
continue
}
contains, err := builtinCall(callable, []any{name})
if err.EXISTS {
return nil, err
}
if anyToBool(contains) {
callable, ok := stack[i].obj["__setindex__"]
if !ok {
continue
}
builtinCall(callable, []any{name, resp})
hasSet = true
break
}
}
varMutex.Lock()
stack[len(stack)-1].obj[x.name] = resp
varMutex.Unlock()
if !hasSet {
callable, ok := stack[len(stack)-1].obj["__setindex__"]
if !ok {
return nil, ArErr{"Type Error", "stack doesn't have __setindex__", v.line, v.path, v.code, true}
}
builtinCall(callable, []any{name, resp})
}
case ArMapGet:
respp, err := runVal(x.VAL, stack, stacklevel+1)
if err.EXISTS {
@@ -251,29 +273,22 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
}
switch y := respp.(type) {
case ArObject:
if y.TYPE != "map" {
if _, ok := y.obj["__setindex__"]; ok {
callable := y.obj["__setindex__"]
r := ArValidToAny(resp)
_, err := runCall(call{
callable: callable,
args: []any{key, r},
line: v.line,
path: v.path,
code: v.code,
}, stack, stacklevel+1)
if _, ok := y.obj["__setindex__"]; ok {
callable := y.obj["__setindex__"]
r := ArValidToAny(resp)
_, err := runCall(call{
callable: callable,
args: []any{key, r},
line: v.line,
path: v.path,
code: v.code,
}, stack, stacklevel+1)
if err.EXISTS {
return nil, err
}
} else {
if isUnhashable(key) {
return nil, ArErr{"Runtime Error", "can't use unhashable type as map key: " + typeof(key), v.line, v.path, v.code, true}
}
varMutex.Lock()
y.obj[key] = resp
varMutex.Unlock()
}
default:
return nil, ArErr{"Runtime Error", "can't set for non map", v.line, v.path, v.code, true}
return nil, ArErr{"Runtime Error", "can't set for non object", v.line, v.path, v.code, true}
}
}
}
@@ -304,9 +319,20 @@ func runDelete(d ArDelete, stack stack, stacklevel int) (any, ArErr) {
switch x := d.value.(type) {
case accessVariable:
for i := len(stack) - 1; i >= 0; i-- {
if _, ok := stack[i].obj[x.name]; ok {
delete(stack[i].obj, x.name)
return nil, ArErr{}
callable, ok := stack[i].obj["__Contains__"]
if !ok {
continue
}
contains, err := builtinCall(callable, []any{x.name})
if err.EXISTS {
return nil, err
}
if anyToBool(contains) {
callable, ok := stack[i].obj["__deleteindex__"]
if !ok {
continue
}
return builtinCall(callable, []any{x.name})
}
}
return nil, ArErr{"Name Error", "variable \"" + x.name + "\" does not exist", d.line, d.path, d.code, true}
@@ -324,7 +350,7 @@ func runDelete(d ArDelete, stack stack, stacklevel int) (any, ArErr) {
}
switch y := respp.(type) {
case ArObject:
if y.TYPE == "array" {
if typeof(y) == "array" {
return nil, ArErr{"Runtime Error", "can't delete from array", d.line, d.path, d.code, true}
}
if isUnhashable(key) {

4
test Executable file
View File

@@ -0,0 +1,4 @@
for FILE in ./tests/*.ar; do
echo "running : $FILE";
./run "$FILE";
done

34
tests/brainfuck.ar Normal file
View File

@@ -0,0 +1,34 @@
let interpret(code) = do
memory = map()
pointer = 0
code_ptr = 0
loops = []
while (code_ptr < code.length) do
command = code[code_ptr]
if (command == '>') pointer = pointer + 1
else if (command == '<') pointer = pointer - 1
else if (command == '+') do
if (pointer not in memory) memory[pointer] = 0
memory[pointer] = memory[pointer] + 1
else if (command == '-') do
if (pointer not in memory) memory[pointer] = 0
memory[pointer] = memory[pointer] - 1
else if (command == '.') term.plain.oneLine(chr(memory.get(pointer, 0)), end='')
else if (command == ',') memory[pointer] = ord(input())
else if (command == '[') do
if (memory.get(pointer, 0) == 0) do
loop_depth = 1
while (loop_depth > 0) do
code_ptr = code_ptr + 1
if (code[code_ptr] == '[') loop_depth = loop_depth + 1
else if (code[code_ptr] == ']') loop_depth = loop_depth - 1
else loops.append(code_ptr)
else if (command == ']') do
if (memory.get(pointer, 0) != 0) code_ptr = loops[-1]
else loops.pop()
code_ptr = code_ptr + 1
interpret('>++++++++[<+++++++++>-]<.>++++[<+++++++>-]<+.+++++++..+++.>>++++++[<+++++++>-]<++.------------.>++++++[<+++++++++>-]<+.<.+++.------.--------.>>>++++[<++++++++>-]<+.')

View File

@@ -11,8 +11,7 @@ name = "william bell"
term.log(getInitials(name))
term.log(name)
let addLastName(name) = do
name.append(" Bell")
let addLastName(name) = name.append(" Bell")
name = "William"
addLastName(name)

View File

@@ -1,8 +1,7 @@
f() = do
a = []
for (i from 0 to 10000000) a.append(i)
for (i from 0 to 10000) a.append(i)
term.log("start")
f()
term.log("end")
time.snooze(100000000)

7
tests/stack test.ar Normal file
View File

@@ -0,0 +1,7 @@
x = 10
do
let x = 20
term.log(x)
term.log(x)

View File

@@ -1,4 +1,3 @@
term.log(" ____ ")
term.log(" /\\ |___ \\ ")
term.log(" / \\ _ __ __ _ ___ _ __ __ ____) |")
term.log(" / /\\ \\ | '__/ _` |/ _ \\| '_ \\ \\ \\ / /__ < ")
@@ -7,5 +6,4 @@ term.log(" /_/ \\_\\_| \\__, |\\___/|_| |_| \\_/|____/ ")
term.log(" __/ | ")
term.log(" |___/ ")
term.log("----------------------------------------------")
term.log("Welcome to ARGON for WASM!")
term.log("write code above and click run to see it work like magic!")
term.log("Welcome to ARGON!")