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 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] char = line[j]
if (char == "," && not in_quotes) do if (char == "," && not in_quotes) do
value = line[start:j].rightstrip("\r").strip() value = line[start:j].rightstrip("\r").strip()
if (value && value[0] == "\"" && value[-1] == "\"") do if (value && value[0] == "\"" && value[-1] == "\"") value = value[1:value.length - 1]
value = value[1:value.length - 1]
value = value.replace("\"\"", "\"") value = value.replace("\"\"", "\"")
values.append(value) values.append(value)
start = j + 1 start = j + 1
else if (char == "\"") do else if (char == "\"") in_quotes = not in_quotes
in_quotes = not in_quotes
if (j == line.length - 1) do if (j == line.length - 1) do
value = line[start:j + 1].rightstrip("\r").strip() value = line[start:j + 1].rightstrip("\r").strip()
if (value && value[0] == "\"" && value[-1] == "\"") do if (value && value[0] == "\"" && value[-1] == "\"") value = value[1:value.length - 1]
value = value[1:value.length - 1]
value = value.replace("\"\"", "\"") value = value.replace("\"\"", "\"")
values.append(value) values.append(value)
data.append(values) data.append(values)

View File

@@ -20,8 +20,8 @@ func isArray(code UNPARSEcode) bool {
func ArArray(arr []any) ArObject { func ArArray(arr []any) ArObject {
val := ArObject{ val := ArObject{
"array",
anymap{ anymap{
"__name__": "array",
"__value__": arr, "__value__": arr,
"length": newNumber().SetUint64(uint64(len(arr))), "length": newNumber().SetUint64(uint64(len(arr))),
}, },
@@ -39,7 +39,7 @@ func ArArray(arr []any) ArObject {
if typeof(a[0]) != "number" { if typeof(a[0]) != "number" {
return nil, ArErr{ return nil, ArErr{
TYPE: "TypeError", TYPE: "TypeError",
message: "index must be a number", message: "dex must be a number",
EXISTS: true, EXISTS: true,
} }
} }
@@ -499,7 +499,6 @@ func ArArray(arr []any) ArObject {
} }
output := []string{} output := []string{}
for _, v := range arr { for _, v := range arr {
v = ArValidToAny(v)
if typeof(v) != "string" { if typeof(v) != "string" {
return nil, ArErr{ return nil, ArErr{
TYPE: "TypeError", TYPE: "TypeError",
@@ -563,6 +562,31 @@ func ArArray(arr []any) ArObject {
} }
return true, ArErr{} 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 return val
} }

View File

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

View File

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

View File

@@ -1,23 +1,28 @@
package main package main
import (
"fmt"
"os"
)
func makeGlobal(allowDocument bool) ArObject { func makeGlobal(allowDocument bool) ArObject {
var vars = Map(anymap{}) var vars = anymap{}
vars.obj["global"] = vars vars["global"] = vars
vars["term"] = ArTerm
if allowDocument { if allowDocument {
vars.obj["document"] = ArDocument vars["document"] = ArDocument
} }
vars.obj["js"] = ArJS vars["js"] = ArJS
vars.obj["term"] = ArTerm vars["number"] = builtinFunc{"number", ArgonNumber}
vars.obj["number"] = builtinFunc{"number", ArgonNumber} vars["string"] = builtinFunc{"string", ArgonString}
vars.obj["string"] = builtinFunc{"string", ArgonString} vars["infinity"] = infinity
vars.obj["infinity"] = infinity vars["map"] = builtinFunc{"map", func(a ...any) (any, ArErr) {
vars.obj["map"] = builtinFunc{"map", func(a ...any) (any, ArErr) {
if len(a) == 0 { if len(a) == 0 {
return Map(anymap{}), ArErr{} return Map(anymap{}), ArErr{}
} }
switch x := a[0].(type) { switch x := a[0].(type) {
case ArObject: case ArObject:
if x.TYPE == "array" { if typeof(x) == "array" {
newmap := anymap{} newmap := anymap{}
for i, v := range x.obj["__value__"].([]any) { for i, v := range x.obj["__value__"].([]any) {
v := ArValidToAny(v) v := ArValidToAny(v)
@@ -35,7 +40,7 @@ func makeGlobal(allowDocument bool) ArObject {
newmap[i] = v newmap[i] = v
} }
return Map(newmap), ArErr{} return Map(newmap), ArErr{}
} else if x.TYPE == "string" { } else if typeof(x) == "string" {
newmap := anymap{} newmap := anymap{}
for i, v := range x.obj["__value__"].(string) { for i, v := range x.obj["__value__"].(string) {
newmap[i] = ArString(string(v)) 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} 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 { if len(a) == 0 {
return ArArray([]any{}), ArErr{} return ArArray([]any{}), ArErr{}
} }
switch x := a[0].(type) { switch x := a[0].(type) {
case ArObject: case ArObject:
if x.TYPE == "array" { if typeof(x) == "array" {
return x, ArErr{} return x, ArErr{}
} else if x.TYPE == "string" { } else if typeof(x) == "string" {
newarray := []any{} newarray := []any{}
for _, v := range x.obj["__value__"].(string) { 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} 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 { if len(a) == 0 {
return false, ArErr{} return false, ArErr{}
} }
return anyToBool(a[0]), ArErr{} return anyToBool(a[0]), ArErr{}
}} }}
vars.obj["time"] = ArTime vars["time"] = ArTime
vars.obj["PI"] = PI vars["PI"] = PI
vars.obj["π"] = PI vars["π"] = PI
vars.obj["e"] = e vars["e"] = e
vars.obj["ln"] = builtinFunc{"ln", ArgonLn} vars["ln"] = builtinFunc{"ln", ArgonLn}
vars.obj["log"] = builtinFunc{"log", ArgonLog} vars["log"] = builtinFunc{"log", ArgonLog}
vars.obj["logN"] = builtinFunc{"logN", ArgonLogN} vars["logN"] = builtinFunc{"logN", ArgonLogN}
vars.obj["thread"] = builtinFunc{"thread", ArThread} vars["thread"] = builtinFunc{"thread", ArThread}
vars.obj["input"] = ArInput vars["input"] = ArInput
vars.obj["round"] = builtinFunc{"round", func(a ...any) (any, ArErr) { vars["round"] = builtinFunc{"round", func(a ...any) (any, ArErr) {
if len(a) == 0 { if len(a) == 0 {
return nil, ArErr{TYPE: "round", message: "round takes 1 argument", return nil, ArErr{TYPE: "round", message: "round takes 1 argument",
EXISTS: true} EXISTS: true}
@@ -109,7 +114,7 @@ func makeGlobal(allowDocument bool) ArObject {
} }
return nil, ArErr{TYPE: "TypeError", message: "Cannot round '" + typeof(a[0]) + "'", EXISTS: true} 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 { if len(a) == 0 {
return nil, ArErr{TYPE: "floor", message: "floor takes 1 argument", return nil, ArErr{TYPE: "floor", message: "floor takes 1 argument",
EXISTS: true} EXISTS: true}
@@ -120,7 +125,7 @@ func makeGlobal(allowDocument bool) ArObject {
} }
return nil, ArErr{TYPE: "TypeError", message: "Cannot floor '" + typeof(a[0]) + "'", EXISTS: true} 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 { if len(a) == 0 {
return nil, ArErr{TYPE: "ceil", message: "ceil takes 1 argument", return nil, ArErr{TYPE: "ceil", message: "ceil takes 1 argument",
EXISTS: true} EXISTS: true}
@@ -132,26 +137,26 @@ func makeGlobal(allowDocument bool) ArObject {
} }
return nil, ArErr{TYPE: "TypeError", message: "Cannot ceil '" + typeof(a[0]) + "'", EXISTS: true} return nil, ArErr{TYPE: "TypeError", message: "Cannot ceil '" + typeof(a[0]) + "'", EXISTS: true}
}} }}
vars.obj["sqrt"] = builtinFunc{"sqrt", ArgonSqrt} vars["sqrt"] = builtinFunc{"sqrt", ArgonSqrt}
vars.obj["file"] = ArFile vars["file"] = ArFile
vars.obj["random"] = ArRandom vars["random"] = ArRandom
vars.obj["json"] = ArJSON vars["json"] = ArJSON
vars.obj["sin"] = ArSin vars["sin"] = ArSin
vars.obj["arcsin"] = ArArcsin vars["arcsin"] = ArArcsin
vars.obj["cos"] = ArCos vars["cos"] = ArCos
vars.obj["arccos"] = ArArccos vars["arccos"] = ArArccos
vars.obj["tan"] = ArTan vars["tan"] = ArTan
vars.obj["arctan"] = ArArctan vars["arctan"] = ArArctan
vars.obj["cosec"] = ArCosec vars["cosec"] = ArCosec
vars.obj["arccosec"] = ArArccosec vars["arccosec"] = ArArccosec
vars.obj["sec"] = ArSec vars["sec"] = ArSec
vars.obj["arcsec"] = ArArcsec vars["arcsec"] = ArArcsec
vars.obj["cot"] = ArCot vars["cot"] = ArCot
vars.obj["arccot"] = ArArccot vars["arccot"] = ArArccot
vars.obj["todeg"] = ArToDeg vars["todeg"] = ArToDeg
vars.obj["torad"] = ArToRad vars["torad"] = ArToRad
vars.obj["abs"] = ArAbs vars["abs"] = ArAbs
vars.obj["dir"] = builtinFunc{"dir", func(a ...any) (any, ArErr) { vars["dir"] = builtinFunc{"dir", func(a ...any) (any, ArErr) {
if len(a) == 0 { if len(a) == 0 {
return ArArray([]any{}), ArErr{} return ArArray([]any{}), ArErr{}
} }
@@ -166,17 +171,17 @@ func makeGlobal(allowDocument bool) ArObject {
} }
return ArArray([]any{}), ArErr{} return ArArray([]any{}), ArErr{}
}} }}
vars.obj["subprocess"] = builtinFunc{"subprocess", ArSubprocess} vars["subprocess"] = builtinFunc{"subprocess", ArSubprocess}
vars.obj["class"] = builtinFunc{"class", func(a ...any) (any, ArErr) { vars["object"] = builtinFunc{"object", func(a ...any) (any, ArErr) {
if len(a) == 0 { if len(a) == 0 {
return nil, ArErr{TYPE: "TypeError", message: "Cannot create class from '" + typeof(a[0]) + "'", EXISTS: true} return nil, ArErr{TYPE: "TypeError", message: "Cannot create class from '" + typeof(a[0]) + "'", EXISTS: true}
} }
switch x := a[0].(type) { switch x := a[0].(type) {
case ArObject: case ArObject:
if x.TYPE == "class" { if typeof(x) == "object" {
return x, ArErr{} return x, ArErr{}
} }
newclass := ArObject{TYPE: "class", obj: anymap{}} newclass := ArObject{obj: anymap{}}
for key, val := range x.obj { for key, val := range x.obj {
newclass.obj[key] = val 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 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 { type Callable struct {
name string
params []string params []string
run any run any
code string code string
@@ -110,12 +111,33 @@ func runCall(c call, stack stack, stacklevel int) (any, ArErr) {
if len(x.params) != len(args) { 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} 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 { 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 ThrowOnNonLoop(openReturn(resp), err)
} }
return nil, ArErr{"Runtime Error", "type '" + typeof(callable) + "' is not callable", c.line, c.path, c.code, true} 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" { if typeof(args[0]) != "string" {
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "read takes a string not type '" + typeof(args[0]) + "'", EXISTS: true} 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) filename := args[0].(string)
file, err := os.Open(filename) file, err := os.Open(filename)
if err != nil { if err != nil {
@@ -58,6 +59,7 @@ func ArWrite(args ...any) (any, ArErr) {
if typeof(args[0]) != "string" { if typeof(args[0]) != "string" {
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "write takes a string not type '" + typeof(args[0]) + "'", EXISTS: true} 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) filename := args[0].(string)
file, err := os.Create(filename) file, err := os.Create(filename)
if err != nil { if err != nil {

View File

@@ -1,13 +1,11 @@
package main package main
import ( import (
"fmt"
"strings" "strings"
) )
type ArObject struct { type ArObject struct {
TYPE string obj anymap
obj anymap
} }
type anymap map[any]any 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)+\]( *)`) var indexGetCompile = makeRegex(`(.|\n)+\[(.|\n)+\]( *)`)
type ArMapGet struct { type ArMapGet struct {
VAL any VAL any
args []any args []any
index bool line int
line int code string
code string path string
path string
} }
func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) { 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) { switch m := resp.(type) {
case ArObject: case ArObject:
if r.index && m.TYPE != "map" { if _, ok := m.obj["__getindex__"]; ok {
if _, ok := m.obj["__getindex__"]; ok { callable := m.obj["__getindex__"]
callable := m.obj["__getindex__"] resp, err := runCall(call{
resp, err := runCall(call{ callable: callable,
callable: callable, args: r.args,
args: r.args, line: r.line,
line: r.line, path: r.path,
path: r.path, code: r.code,
code: r.code, }, stack, stacklevel+1)
}, stack, stacklevel+1) if !err.EXISTS {
if !err.EXISTS { return resp, ArErr{}
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) key, err := runVal(r.args[0], stack, stacklevel+1)
@@ -111,7 +75,7 @@ func mapGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapGet
if !worked { if !worked {
return ArMapGet{}, false, err, i 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 { func isIndexGet(code UNPARSEcode) bool {
@@ -149,7 +113,7 @@ func indexGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapG
} }
continue 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{ return ArMapGet{}, false, ArErr{
"Syntax Error", "Syntax Error",
@@ -161,7 +125,19 @@ func indexGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapG
}, 1 }, 1
} }
var hashabletypes = []string{
"number",
"string",
"bool",
"null",
}
func isUnhashable(val any) bool { func isUnhashable(val any) bool {
keytype := typeof(val) 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) char := make([]byte, 1)
_, err := os.Stdin.Read(char) _, err := os.Stdin.Read(char)
if err != nil { if err != nil {
fmt.Println(err) return "", err
break
} }
if char[0] == 3 || char[0] == 4 { if char[0] == 3 || char[0] == 4 {
return "", fmt.Errorf("keyboard interupt") return "", fmt.Errorf("keyboard interupt")

View File

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

View File

@@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"strings" "strings"
"sync"
) )
var mapCompiled = makeRegex(`( *)\{(((( *).+( *):( *).+( *))|(` + spacelessVariable + `))(( *)\,(( *).+( *):( *).+( *))|(` + spacelessVariable + `)))*\}( *)`) var mapCompiled = makeRegex(`( *)\{(((( *).+( *):( *).+( *))|(` + spacelessVariable + `))(( *)\,(( *).+( *):( *).+( *))|(` + spacelessVariable + `)))*\}( *)`)
@@ -25,16 +26,146 @@ func parseMap(code UNPARSEcode) (any, UNPARSEcode) {
return nil, UNPARSEcode{} return nil, UNPARSEcode{}
} }
func Map(val anymap) ArObject { func Map(m anymap) ArObject {
var mutex = sync.RWMutex{}
return ArObject{ return ArObject{
TYPE: "map", obj: anymap{
obj: val, "__value__": m,
} "__name__": "map",
} "get": builtinFunc{
"get",
func Class(val anymap) ArObject { func(args ...any) (any, ArErr) {
return ArObject{ if len(args) < 1 || len(args) > 2 {
TYPE: "class", return nil, ArErr{
obj: val, 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 { if err.EXISTS {
return false, err return false, err
} }
if x, ok := resp.(ArObject); ok { if x, ok := resp2.(ArObject); ok {
if y, ok := x.obj["__NotContains__"]; ok { if y, ok := x.obj["__NotContains__"]; ok {
return runCall( return runCall(
call{ call{
y, y,
[]any{resp2}, []any{resp},
o.code, o.code,
o.line, o.line,
o.path, o.path,
@@ -571,7 +571,7 @@ func calcNotIn(o operationType, stack stack, stacklevel int) (any, ArErr) {
} }
return false, ArErr{ return false, ArErr{
"Runtime Error", "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.line,
o.path, o.path,
o.code, o.code,
@@ -697,7 +697,11 @@ func calcMod(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 = 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 continue
} else if x, ok := output.(ArObject); ok { } else if x, ok := output.(ArObject); ok {
if y, ok := x.obj["__Modulo__"]; 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" 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 { if len(list) <= 1 {
return list, ArErr{} return list, ArErr{}
} }
pivot := list[0] pivot := list[0]
var left []interface{} var left []any
var right []interface{} var right []any
var cache = make(keyCache) var cache = make(keyCache)
@@ -51,7 +51,7 @@ func quickSort(list []interface{}, getKey func(interface{}) (interface{}, ArErr)
return append(append(left, pivot), right...), 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) key := ArValidToAny(index)
if cacheval, ok := cache[key]; ok { if cacheval, ok := cache[key]; ok {
return cacheval, ArErr{} return cacheval, ArErr{}

View File

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

View File

@@ -98,7 +98,7 @@ var ArTerm = Map(anymap{
"time": builtinFunc{"time", func(args ...any) (any, ArErr) { "time": builtinFunc{"time", func(args ...any) (any, ArErr) {
var id any = nil var id any = nil
if len(args) > 0 { if len(args) > 0 {
id = args[0] id = ArValidToAny(args[0])
} }
timing[id] = time.Now() timing[id] = time.Now()
return nil, ArErr{} return nil, ArErr{}
@@ -107,7 +107,7 @@ var ArTerm = Map(anymap{
"timeEnd": builtinFunc{"timeEnd", func(args ...any) (any, ArErr) { "timeEnd": builtinFunc{"timeEnd", func(args ...any) (any, ArErr) {
var id any = nil var id any = nil
if len(args) > 0 { if len(args) > 0 {
id = args[0] id = ArValidToAny(args[0])
} }
if _, ok := timing[id]; !ok { if _, ok := timing[id]; !ok {
return nil, ArErr{TYPE: "TypeError", message: "Cannot find timer with id '" + fmt.Sprint(id) + "'", EXISTS: true} 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{} 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) var MicroSeconds = newNumber().SetInt64(1000000)
func ArTimeClass(N time.Time) ArObject { func ArTimeClass(N time.Time) ArObject {
return Class(anymap{ m := Map(anymap{
"__value__": newNumber().Quo(newNumber().SetInt64(N.UnixMicro()), MicroSeconds),
"year": builtinFunc{ "year": builtinFunc{
"year", "year",
func(a ...any) (any, ArErr) { 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{ var ArTime = Map(anymap{
@@ -112,19 +113,43 @@ var ArTime = Map(anymap{
}}, }},
"parse": builtinFunc{"parse", func(a ...any) (any, ArErr) { "parse": builtinFunc{"parse", func(a ...any) (any, ArErr) {
if len(a) == 1 { 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)) N, err := time.Parse(time.UnixDate, a[0].(string))
if err != nil { if err != nil {
return nil, ArErr{ return nil, ArErr{
TYPE: "ArErr", TYPE: "Runtime Error",
message: err.Error(), message: err.Error(),
} }
} }
return ArTimeClass(N), ArErr{} return ArTimeClass(N), ArErr{}
} else if len(a) > 1 { } 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)) N, err := time.Parse(a[0].(string), a[1].(string))
if err != nil { if err != nil {
return nil, ArErr{ return nil, ArErr{
TYPE: "ArErr", TYPE: "Runtime Error",
message: err.Error(), message: err.Error(),
EXISTS: true, EXISTS: true,
} }
@@ -132,17 +157,26 @@ var ArTime = Map(anymap{
return ArTimeClass(N), ArErr{} return ArTimeClass(N), ArErr{}
} }
return nil, ArErr{ return nil, ArErr{
TYPE: "ArErr", TYPE: "Runtime Error",
message: "parse requires 2 arguments", message: "parse requires 1 or 2 arguments",
EXISTS: true, EXISTS: true,
} }
}}, }},
"parseInLocation": builtinFunc{"parseInLocation", func(a ...any) (any, ArErr) { "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) N, err := time.ParseInLocation(a[0].(string), a[1].(string), time.Local)
if err != nil { if err != nil {
return nil, ArErr{ return nil, ArErr{
TYPE: "ArErr", TYPE: "Runtime Error",
message: err.Error(), message: err.Error(),
EXISTS: true, EXISTS: true,
} }
@@ -150,18 +184,26 @@ var ArTime = Map(anymap{
return ArTimeClass(N), ArErr{} return ArTimeClass(N), ArErr{}
} }
return nil, ArErr{ return nil, ArErr{
TYPE: "ArErr", TYPE: "Runtime Error",
message: "parseInLocation requires 3 arguments", message: "parseInLocation requires 2 arguments",
EXISTS: true, EXISTS: true,
} }
}, },
}, },
"date": builtinFunc{"date", func(a ...any) (any, ArErr) { "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)) N, err := time.Parse(time.UnixDate, a[0].(string))
if err != nil { if err != nil {
return nil, ArErr{ return nil, ArErr{
TYPE: "ArErr", TYPE: "Runtime Error",
message: err.Error(), message: err.Error(),
EXISTS: true, EXISTS: true,
} }
@@ -169,45 +211,66 @@ var ArTime = Map(anymap{
return ArTimeClass(N), ArErr{} return ArTimeClass(N), ArErr{}
} }
return nil, ArErr{ return nil, ArErr{
TYPE: "ArErr", TYPE: "Runtime Error",
message: "date requires 1 argument", message: "date requires 1 argument",
EXISTS: true, EXISTS: true,
} }
}, },
}, },
"Unix": builtinFunc{"Unix", func(a ...any) (any, ArErr) { "unix": builtinFunc{"unix", func(a ...any) (any, ArErr) {
if len(a) > 1 { 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() sec, _ := a[0].(number).Float64()
nsec, _ := a[1].(number).Float64() nsec, _ := a[1].(number).Float64()
return ArTimeClass(time.Unix(int64(sec), int64(nsec))), ArErr{} return ArTimeClass(time.Unix(int64(sec), int64(nsec))), ArErr{}
} }
return nil, ArErr{ return nil, ArErr{
TYPE: "ArErr", TYPE: "Runtime Error",
message: "Unix requires 2 arguments", message: "unix requires 2 arguments",
EXISTS: true, EXISTS: true,
} }
}, },
}, },
"UnixMilli": builtinFunc{"UnixMilli", func(a ...any) (any, ArErr) { "unixMilli": builtinFunc{"unixMilli", func(a ...any) (any, ArErr) {
if len(a) > 0 { 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() msec, _ := a[0].(number).Float64()
return ArTimeClass(time.UnixMilli(int64(msec))), ArErr{} return ArTimeClass(time.UnixMilli(int64(msec))), ArErr{}
} }
return nil, ArErr{ return nil, ArErr{
TYPE: "ArErr", TYPE: "Runtime Error",
message: "UnixMilli requires 1 argument", message: "UnixMilli requires 1 argument",
EXISTS: true, EXISTS: true,
} }
}, },
}, },
"UnixMicro": builtinFunc{"UnixMicro", func(a ...any) (any, ArErr) { "unixMicro": builtinFunc{"unixMicro", func(a ...any) (any, ArErr) {
if len(a) > 0 { 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() usec, _ := a[0].(number).Float64()
return ArTimeClass(time.UnixMicro(int64(usec))), ArErr{} return ArTimeClass(time.UnixMicro(int64(usec))), ArErr{}
} }
return nil, ArErr{ return nil, ArErr{
TYPE: "ArErr", TYPE: "Runtime Error",
message: "UnixMicro requires 1 argument", message: "unixMicro requires 1 argument",
EXISTS: true, EXISTS: true,
} }
}, },

View File

@@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"math" "math"
"sort"
"strconv" "strconv"
"strings" "strings"
@@ -78,6 +79,9 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
return "{}" return "{}"
} }
keys := make([]any, len(x)) 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 i := 0
for k := range x { for k := range x {
@@ -148,7 +152,7 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
if colored { if colored {
output = append(output, "\x1b[38;5;240m") output = append(output, "\x1b[38;5;240m")
} }
output = append(output, "<function>") output = append(output, "<function "+x.name+">")
if colored { if colored {
output = append(output, "\x1b[0m") 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 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) operation, worked, err, step := parseOperations(code, index, codelines)
if worked { if worked {
@@ -113,16 +119,9 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i
} }
if isNegative(code) { if isNegative(code) {
return parseNegative(code, index, codelines) return parseNegative(code, index, codelines)
} else if isCall(code) { } else if isMapGet(code) {
resp, worked, err, i = parseCall(code, index, codelines)
if worked {
return resp, worked, err, i
}
}
if isMapGet(code) {
return mapGetParse(code, index, codelines) return mapGetParse(code, index, codelines)
} } else if isIndexGet(code) {
if isIndexGet(code) {
resp, worked, err, i = indexGetParse(code, index, codelines) resp, worked, err, i = indexGetParse(code, index, codelines)
if worked { if worked {
return resp, worked, err, i 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) { func runTryCatch(t TryCatch, stack stack, stacklevel int) (any, ArErr) {
val, err := runVal(t.Try, stack, stacklevel) val, err := runVal(t.Try, stack, stacklevel)
if err.EXISTS { if err.EXISTS {
scope := newscope() vars := anymap{}
scope.obj[t.errorName] = Map(anymap{ vars[t.errorName] = Map(anymap{
"type": err.TYPE, "type": err.TYPE,
"message": err.message, "message": err.message,
"line": newNumber().SetInt64(int64(err.line)), "line": newNumber().SetInt64(int64(err.line)),
"path": err.path, "path": err.path,
"code": err.code, "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 { if err.EXISTS {
return nil, err return nil, err
} }

View File

@@ -19,7 +19,13 @@ func typeof(val any) string {
case builtinFunc: case builtinFunc:
return "function" return "function"
case ArObject: 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: case accessVariable:
return "variable" return "variable"
} }

View File

@@ -2,19 +2,16 @@ package main
import ( import (
"strings" "strings"
"sync"
) )
var spacelessVariable = `([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*` var spacelessVariable = `([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*`
var SpacelessVariableCompiled = makeRegex(spacelessVariable) 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 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 setVariableCompile = makeRegex(`( *)(let( +))(.|\n)+( *)=(.|\n)+`)
var autoAsignVariableCompile = makeRegex(`(.|\n)+=(.|\n)+`) var autoAsignVariableCompile = makeRegex(`(.|\n)+=(.|\n)+`)
var deleteVariableCompile = makeRegex(`( *)delete( +)(.|\n)+( *)`) var deleteVariableCompile = makeRegex(`( *)delete( +)(.|\n)+( *)`)
var varMutex = sync.RWMutex{}
var blockedVariableNames = map[string]bool{ var blockedVariableNames = map[string]bool{
"if": true, "if": true,
"else": true, "else": true,
@@ -80,11 +77,20 @@ func parseVariable(code UNPARSEcode) (accessVariable, bool, ArErr, int) {
func readVariable(v accessVariable, stack stack) (any, ArErr) { func readVariable(v accessVariable, stack stack) (any, ArErr) {
for i := len(stack) - 1; i >= 0; i-- { for i := len(stack) - 1; i >= 0; i-- {
varMutex.RLock() callable, ok := stack[i].obj["__Contains__"]
val, ok := stack[i].obj[v.name] if !ok {
varMutex.RUnlock() continue
if ok { }
return val, ArErr{} 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} 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) { func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
var resp any var resp any
if v.function { 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 { } else {
respp, err := runVal(v.value, stack, stacklevel+1) respp, err := runVal(v.value, stack, stacklevel+1)
if err.EXISTS { if err.EXISTS {
@@ -210,32 +216,48 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
} }
if v.TYPE == "let" { if v.TYPE == "let" {
varMutex.RLock() stackcallable, ok := stack[len(stack)-1].obj["__setindex__"]
_, ok := stack[len(stack)-1].obj[v.toset.(accessVariable).name] if !ok {
varMutex.RUnlock() return nil, ArErr{"Type Error", "stack doesn't have __setindex__", v.line, v.path, v.code, true}
if ok { }
return nil, ArErr{"Name Error", "variable \"" + v.toset.(accessVariable).name + "\" already exists", 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 { } else {
switch x := v.toset.(type) { switch x := v.toset.(type) {
case accessVariable: 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-- { for i := len(stack) - 1; i >= 0; i-- {
varMutex.RLock() callable, ok := stack[i].obj["__Contains__"]
_, ok := stack[i].obj[x.name] if !ok {
varMutex.RUnlock() continue
if ok { }
varMutex.Lock() contains, err := builtinCall(callable, []any{name})
stack[i].obj[x.name] = resp if err.EXISTS {
varMutex.Unlock() return nil, err
return ThrowOnNonLoop(resp, ArErr{}) }
if anyToBool(contains) {
callable, ok := stack[i].obj["__setindex__"]
if !ok {
continue
}
builtinCall(callable, []any{name, resp})
hasSet = true
break
} }
} }
varMutex.Lock() if !hasSet {
stack[len(stack)-1].obj[x.name] = resp callable, ok := stack[len(stack)-1].obj["__setindex__"]
varMutex.Unlock() 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: case ArMapGet:
respp, err := runVal(x.VAL, stack, stacklevel+1) respp, err := runVal(x.VAL, stack, stacklevel+1)
if err.EXISTS { if err.EXISTS {
@@ -251,29 +273,22 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
} }
switch y := respp.(type) { switch y := respp.(type) {
case ArObject: case ArObject:
if y.TYPE != "map" { if _, ok := y.obj["__setindex__"]; ok {
if _, ok := y.obj["__setindex__"]; ok { callable := y.obj["__setindex__"]
callable := y.obj["__setindex__"] r := ArValidToAny(resp)
r := ArValidToAny(resp) _, err := runCall(call{
_, err := runCall(call{ callable: callable,
callable: callable, args: []any{key, r},
args: []any{key, r}, line: v.line,
line: v.line, path: v.path,
path: v.path, code: v.code,
code: v.code, }, stack, stacklevel+1)
}, stack, stacklevel+1) if err.EXISTS {
return nil, err 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: 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) { switch x := d.value.(type) {
case accessVariable: case accessVariable:
for i := len(stack) - 1; i >= 0; i-- { for i := len(stack) - 1; i >= 0; i-- {
if _, ok := stack[i].obj[x.name]; ok { callable, ok := stack[i].obj["__Contains__"]
delete(stack[i].obj, x.name) if !ok {
return nil, ArErr{} 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} 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) { switch y := respp.(type) {
case ArObject: 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} return nil, ArErr{"Runtime Error", "can't delete from array", d.line, d.path, d.code, true}
} }
if isUnhashable(key) { 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(getInitials(name))
term.log(name) term.log(name)
let addLastName(name) = do let addLastName(name) = name.append(" Bell")
name.append(" Bell")
name = "William" name = "William"
addLastName(name) addLastName(name)

View File

@@ -1,8 +1,7 @@
f() = do f() = do
a = [] a = []
for (i from 0 to 10000000) a.append(i) for (i from 0 to 10000) a.append(i)
term.log("start") term.log("start")
f() f()
term.log("end") 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(" / \\ _ __ __ _ ___ _ __ __ ____) |") term.log(" / \\ _ __ __ _ ___ _ __ __ ____) |")
term.log(" / /\\ \\ | '__/ _` |/ _ \\| '_ \\ \\ \\ / /__ < ") term.log(" / /\\ \\ | '__/ _` |/ _ \\| '_ \\ \\ \\ / /__ < ")
@@ -7,5 +6,4 @@ term.log(" /_/ \\_\\_| \\__, |\\___/|_| |_| \\_/|____/ ")
term.log(" __/ | ") term.log(" __/ | ")
term.log(" |___/ ") term.log(" |___/ ")
term.log("----------------------------------------------") term.log("----------------------------------------------")
term.log("Welcome to ARGON for WASM!") term.log("Welcome to ARGON!")
term.log("write code above and click run to see it work like magic!")