mirror of
https://github.com/Open-Argon/argon-v3.git
synced 2025-12-06 08:56:07 +00:00
make arrays an object
This commit is contained in:
237
src/array.go
237
src/array.go
@@ -5,7 +5,7 @@ import "strings"
|
||||
var arrayCompile = makeRegex(`( *)\[(.|\n)*\]( *)`)
|
||||
|
||||
type CreateArray struct {
|
||||
value ArArray
|
||||
value []any
|
||||
line int
|
||||
code string
|
||||
path string
|
||||
@@ -15,6 +15,233 @@ func isArray(code UNPARSEcode) bool {
|
||||
return arrayCompile.MatchString(code.code)
|
||||
}
|
||||
|
||||
func ArArray(arr []any) ArObject {
|
||||
val := ArObject{
|
||||
"array",
|
||||
anymap{
|
||||
"__value__": arr,
|
||||
"length": len(arr),
|
||||
},
|
||||
}
|
||||
val.obj["remove"] = builtinFunc{
|
||||
"remove",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "missing argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if typeof(args[0]) != "number" {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be a number",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if !args[0].(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be an integer",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
num := int(args[0].(number).Num().Int64())
|
||||
if num < 0 || num >= len(arr) {
|
||||
return nil, ArErr{
|
||||
TYPE: "IndexError",
|
||||
message: "index out of range",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
arr = append(arr[:num], arr[num+1:]...)
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return nil, ArErr{}
|
||||
}}
|
||||
val.obj["append"] = builtinFunc{
|
||||
"append",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) == 0 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "missing argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
arr = append(arr, args...)
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return nil, ArErr{}
|
||||
},
|
||||
}
|
||||
val.obj["insert"] = builtinFunc{
|
||||
"insert",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) < 2 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "missing argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if typeof(args[0]) != "number" {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be a number",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if !args[0].(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be an integer",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
num := int(args[0].(number).Num().Int64())
|
||||
if num < 0 || num > len(arr) {
|
||||
return nil, ArErr{
|
||||
TYPE: "IndexError",
|
||||
message: "index out of range",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
arr = append(arr[:num], append(args[1:], arr[num:]...)...)
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return nil, ArErr{}
|
||||
},
|
||||
}
|
||||
val.obj["pop"] = builtinFunc{
|
||||
"pop",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) > 1 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "too many arguments",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if len(args) == 1 {
|
||||
if typeof(args[0]) != "number" {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be a number",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if !args[0].(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be an integer",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
num := int(args[0].(number).Num().Int64())
|
||||
if num < 0 || num >= len(arr) {
|
||||
return nil, ArErr{
|
||||
TYPE: "IndexError",
|
||||
message: "index out of range",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
v := arr[num]
|
||||
arr = append(arr[:num], arr[num+1:]...)
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return v, ArErr{}
|
||||
}
|
||||
v := arr[len(arr)-1]
|
||||
arr = arr[:len(arr)-1]
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return v, ArErr{}
|
||||
},
|
||||
}
|
||||
val.obj["clear"] = builtinFunc{
|
||||
"clear",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) != 0 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "too many arguments",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
arr = []any{}
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return nil, ArErr{}
|
||||
},
|
||||
}
|
||||
val.obj["extend"] = builtinFunc{
|
||||
"extend",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "missing argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if typeof(args[0]) != "array" {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be an array",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
arr = append(arr, args[0].(ArObject).obj["__value__"].([]any)...)
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return nil, ArErr{}
|
||||
},
|
||||
}
|
||||
val.obj["map"] = builtinFunc{
|
||||
"map",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "missing argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if typeof(args[0]) != "function" {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be a function",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
newarr := []any{}
|
||||
for _, v := range arr {
|
||||
vv, err := runCall(call{
|
||||
args[0],
|
||||
[]any{v}, "", 0, "",
|
||||
}, stack{vars, newscope()}, 0)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
}
|
||||
newarr = append(newarr, vv)
|
||||
}
|
||||
return ArArray(newarr), ArErr{}
|
||||
},
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func potentialAnyArrayToArArray(arr any) any {
|
||||
switch arr := arr.(type) {
|
||||
case []any:
|
||||
return ArArray(arr)
|
||||
default:
|
||||
return arr
|
||||
}
|
||||
}
|
||||
|
||||
func parseArray(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, ArErr, int) {
|
||||
trimmed := strings.TrimSpace(code.code)
|
||||
trimmed = trimmed[1 : len(trimmed)-1]
|
||||
@@ -27,14 +254,14 @@ func parseArray(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool
|
||||
}, worked, err, 1
|
||||
}
|
||||
|
||||
func runArray(a CreateArray, stack stack, stacklevel int) ([]any, ArErr) {
|
||||
var array ArArray
|
||||
func runArray(a CreateArray, stack stack, stacklevel int) (ArObject, ArErr) {
|
||||
var array []any
|
||||
for _, val := range a.value {
|
||||
val, err := runVal(val, stack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
return ArObject{}, err
|
||||
}
|
||||
array = append(array, val)
|
||||
}
|
||||
return array, ArErr{}
|
||||
return ArArray(array), ArErr{}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,11 @@ func anyToBool(x any) bool {
|
||||
return x
|
||||
case nil:
|
||||
return false
|
||||
case ArMap:
|
||||
return len(x) != 0
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
return len(x.obj["__value__"].([]any)) != 0
|
||||
}
|
||||
return len(x.obj) != 0
|
||||
case builtinFunc:
|
||||
return true
|
||||
case Callable:
|
||||
|
||||
156
src/built-ins.go
156
src/built-ins.go
@@ -1,97 +1,97 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var vars = scope{}
|
||||
var vars = Map(anymap{})
|
||||
|
||||
func init() {
|
||||
vars["global"] = vars
|
||||
vars["term"] = ArTerm
|
||||
vars["input"] = builtinFunc{"input", ArgonInput}
|
||||
vars["number"] = builtinFunc{"number", ArgonNumber}
|
||||
vars["string"] = builtinFunc{"string", ArgonString}
|
||||
vars["infinity"] = infinity
|
||||
vars["length"] = builtinFunc{"length", func(a ...any) (any, ArErr) {
|
||||
vars.obj["global"] = vars
|
||||
vars.obj["term"] = ArTerm
|
||||
vars.obj["input"] = builtinFunc{"input", ArgonInput}
|
||||
vars.obj["number"] = builtinFunc{"number", ArgonNumber}
|
||||
vars.obj["string"] = builtinFunc{"string", ArgonString}
|
||||
vars.obj["infinity"] = infinity
|
||||
vars.obj["length"] = builtinFunc{"length", func(a ...any) (any, ArErr) {
|
||||
switch x := a[0].(type) {
|
||||
case string:
|
||||
return len(x), ArErr{}
|
||||
case ArMap:
|
||||
return len(x), ArErr{}
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
return len(x.obj["__value__"].([]any)), ArErr{}
|
||||
}
|
||||
return len(x.obj), ArErr{}
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot get length of " + typeof(a[0]), EXISTS: true}
|
||||
}}
|
||||
vars["map"] = builtinFunc{"map", func(a ...any) (any, ArErr) {
|
||||
vars.obj["map"] = builtinFunc{"map", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return ArMap{}, ArErr{}
|
||||
return Map(anymap{}), ArErr{}
|
||||
}
|
||||
switch x := a[0].(type) {
|
||||
case ArMap:
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
newmap := anymap{}
|
||||
for i, v := range x.obj["__value__"].([]any) {
|
||||
switch y := v.(type) {
|
||||
case []any:
|
||||
if len(y) == 2 {
|
||||
if isUnhashable(y[0]) {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot use unhashable value as key: " + typeof(y[0]), EXISTS: true}
|
||||
}
|
||||
newmap[y[0]] = y[1]
|
||||
continue
|
||||
}
|
||||
}
|
||||
newmap[i] = v
|
||||
}
|
||||
return Map(newmap), ArErr{}
|
||||
}
|
||||
return x, ArErr{}
|
||||
case string:
|
||||
newmap := ArMap{}
|
||||
newmap := anymap{}
|
||||
for i, v := range x {
|
||||
newmap[i] = string(v)
|
||||
}
|
||||
return newmap, ArErr{}
|
||||
case ArArray:
|
||||
newmap := ArMap{}
|
||||
for i, v := range x {
|
||||
switch y := v.(type) {
|
||||
case ArArray:
|
||||
if len(y) == 2 {
|
||||
if isUnhashable(y[0]) {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot use unhashable value as key: " + typeof(y[0]), EXISTS: true}
|
||||
}
|
||||
newmap[y[0]] = y[1]
|
||||
continue
|
||||
}
|
||||
}
|
||||
newmap[i] = v
|
||||
}
|
||||
return newmap, ArErr{}
|
||||
return Map(newmap), ArErr{}
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot create map from '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["array"] = builtinFunc{"array", func(a ...any) (any, ArErr) {
|
||||
vars.obj["array"] = builtinFunc{"array", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return ArArray{}, ArErr{}
|
||||
return ArArray([]any{}), ArErr{}
|
||||
}
|
||||
switch x := a[0].(type) {
|
||||
case ArArray:
|
||||
return x, ArErr{}
|
||||
case string:
|
||||
newarray := ArArray{}
|
||||
newarray := []any{}
|
||||
for _, v := range x {
|
||||
newarray = append(newarray, string(v))
|
||||
}
|
||||
return newarray, ArErr{}
|
||||
case ArMap:
|
||||
newarray := ArArray{}
|
||||
for key, val := range x {
|
||||
newarray = append(newarray, ArArray{key, val})
|
||||
return ArArray(newarray), ArErr{}
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
return x, ArErr{}
|
||||
}
|
||||
return newarray, ArErr{}
|
||||
newarray := []any{}
|
||||
for key, val := range x.obj {
|
||||
newarray = append(newarray, []any{key, val})
|
||||
}
|
||||
return ArArray(newarray), ArErr{}
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot create array from '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["boolean"] = builtinFunc{"boolean", func(a ...any) (any, ArErr) {
|
||||
vars.obj["boolean"] = builtinFunc{"boolean", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return false, ArErr{}
|
||||
}
|
||||
return anyToBool(a[0]), 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["round"] = builtinFunc{"round", func(a ...any) (any, 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["round"] = builtinFunc{"round", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return nil, ArErr{TYPE: "round", message: "round takes 1 argument",
|
||||
EXISTS: true}
|
||||
@@ -115,7 +115,7 @@ func init() {
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot round '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["floor"] = builtinFunc{"floor", func(a ...any) (any, ArErr) {
|
||||
vars.obj["floor"] = builtinFunc{"floor", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return nil, ArErr{TYPE: "floor", message: "floor takes 1 argument",
|
||||
EXISTS: true}
|
||||
@@ -126,7 +126,7 @@ func init() {
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot floor '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["ceil"] = builtinFunc{"ceil", func(a ...any) (any, ArErr) {
|
||||
vars.obj["ceil"] = builtinFunc{"ceil", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return nil, ArErr{TYPE: "ceil", message: "ceil takes 1 argument",
|
||||
EXISTS: true}
|
||||
@@ -138,36 +138,10 @@ func init() {
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot ceil '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["append"] = builtinFunc{"append", func(a ...any) (any, ArErr) {
|
||||
if len(a) != 2 {
|
||||
return nil, ArErr{TYPE: "append", message: "append takes 2 arguments, got " + fmt.Sprint(len(a)),
|
||||
EXISTS: true}
|
||||
}
|
||||
switch x := a[0].(type) {
|
||||
case ArArray:
|
||||
return append(x, a[1]), ArErr{}
|
||||
case string:
|
||||
if typeof(a[1]) != "string" {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot append '" + typeof(a[1]) + "' to string", EXISTS: true}
|
||||
}
|
||||
return strings.Join([]string{x, a[1].(string)}, ""), ArErr{}
|
||||
case ArMap:
|
||||
if typeof(a[1]) != "array" {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot append '" + typeof(a[1]) + "' to map", EXISTS: true}
|
||||
}
|
||||
y := a[1].(ArArray)
|
||||
if len(y) != 2 {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot append '" + typeof(a[1]) + "' to map", EXISTS: true}
|
||||
}
|
||||
x[y[0]] = y[1]
|
||||
return x, ArErr{}
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot append to '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["sqrt"] = builtinFunc{"sqrt", ArgonSqrt}
|
||||
vars["file"] = ArFile
|
||||
vars["random"] = ArRandom
|
||||
vars["json"] = ArJSON
|
||||
vars["sin"] = ArSin
|
||||
vars["arcsin"] = ArArcsin
|
||||
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
|
||||
}
|
||||
|
||||
20
src/call.go
20
src/call.go
@@ -15,6 +15,14 @@ type call struct {
|
||||
path string
|
||||
}
|
||||
|
||||
type Callable struct {
|
||||
params []string
|
||||
run any
|
||||
code string
|
||||
stack stack
|
||||
line int
|
||||
}
|
||||
|
||||
func isCall(code UNPARSEcode) bool {
|
||||
return callCompile.MatchString(code.code)
|
||||
}
|
||||
@@ -30,7 +38,7 @@ func parseCall(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool,
|
||||
for i := 1; i < len(splitby); i++ {
|
||||
name := strings.Join(splitby[0:i], "(")
|
||||
argstr := strings.Join(splitby[i:], "(")
|
||||
args, success, argserr := getValuesFromLetter(argstr, ",", index, codelines, true)
|
||||
args, success, argserr := getValuesFromLetter(argstr, ",", index, codelines, false)
|
||||
arguments = args
|
||||
if !success {
|
||||
if i == len(splitby)-1 {
|
||||
@@ -68,13 +76,13 @@ func runCall(c call, stack stack, stacklevel int) (any, ArErr) {
|
||||
return nil, err
|
||||
}
|
||||
switch x := callable_.(type) {
|
||||
case ArMap:
|
||||
callable_ = x["__call__"]
|
||||
case ArObject:
|
||||
callable_ = x.obj["__call__"]
|
||||
}
|
||||
callable = callable_
|
||||
}
|
||||
args := []any{}
|
||||
level := append(stack, scope{})
|
||||
level := append(stack, newscope())
|
||||
for _, arg := range c.args {
|
||||
resp, err := runVal(arg, level, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
@@ -101,9 +109,9 @@ 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 := scope{}
|
||||
level := newscope()
|
||||
for i, param := range x.params {
|
||||
level[param] = args[i]
|
||||
level.obj[param] = args[i]
|
||||
}
|
||||
resp, err := runVal(x.run, append(x.stack, level), stacklevel+1)
|
||||
return ThrowOnNonLoop(openReturn(resp), err)
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package main
|
||||
|
||||
type Callable struct {
|
||||
params []string
|
||||
run any
|
||||
code string
|
||||
stack stack
|
||||
line int
|
||||
}
|
||||
@@ -49,7 +49,7 @@ func parseDoWrap(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, boo
|
||||
}
|
||||
|
||||
func runDoWrap(d dowrap, stack stack, stacklevel int) (any, ArErr) {
|
||||
newstack := append(stack, scope{})
|
||||
newstack := append(stack, newscope())
|
||||
for _, v := range d.run {
|
||||
val, err := runVal(v, newstack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
|
||||
36
src/file.go
36
src/file.go
@@ -7,10 +7,10 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
var ArFile = ArMap{
|
||||
var ArFile = Map(anymap{
|
||||
"read": builtinFunc{"read", ArRead},
|
||||
"write": builtinFunc{"write", ArWrite},
|
||||
}
|
||||
})
|
||||
|
||||
func readtext(file *os.File) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
@@ -23,68 +23,68 @@ func readtext(file *os.File) (string, error) {
|
||||
|
||||
func ArRead(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "read takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "read takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "string" {
|
||||
return ArMap{}, 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}
|
||||
}
|
||||
filename := args[0].(string)
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return ArMap{
|
||||
return Map(anymap{
|
||||
"text": builtinFunc{"text", func(...any) (any, ArErr) {
|
||||
text, err := readtext(file)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return text, ArErr{}
|
||||
}},
|
||||
"json": builtinFunc{"json", func(...any) (any, ArErr) {
|
||||
text, err := readtext(file)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return jsonparse(text), ArErr{}
|
||||
}},
|
||||
}, ArErr{}
|
||||
}), ArErr{}
|
||||
}
|
||||
|
||||
func ArWrite(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "write takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "write takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "string" {
|
||||
return ArMap{}, 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}
|
||||
}
|
||||
filename := args[0].(string)
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return ArMap{
|
||||
return Map(anymap{
|
||||
"text": builtinFunc{"text", func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "text takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "text takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "string" {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "text takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "text takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
}
|
||||
file.Write([]byte(args[0].(string)))
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
"json": builtinFunc{"json", func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "json takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "json takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
jsonstr, err := jsonstringify(args[0], 0)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
file.Write([]byte(jsonstr))
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
}, ArErr{}
|
||||
}), ArErr{}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,15 +5,19 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ArMap = map[any]any
|
||||
type ArArray = []any
|
||||
type ArObject struct {
|
||||
TYPE string
|
||||
obj anymap
|
||||
}
|
||||
|
||||
type anymap map[any]any
|
||||
|
||||
var mapGetCompile = makeRegex(`(.|\n)+\.([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*( *)`)
|
||||
var indexGetCompile = makeRegex(`(.|\n)+\[(.|\n)+\]( *)`)
|
||||
|
||||
type ArMapGet struct {
|
||||
VAL any
|
||||
args ArArray
|
||||
args []any
|
||||
index bool
|
||||
line int
|
||||
code string
|
||||
@@ -26,7 +30,14 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
||||
return nil, err
|
||||
}
|
||||
switch m := resp.(type) {
|
||||
case ArMap:
|
||||
case ArObject:
|
||||
switch m.TYPE {
|
||||
case "array":
|
||||
resp, err := getFromArArray(m, r, stack, stacklevel+1)
|
||||
if !err.EXISTS {
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
if len(r.args) > 1 {
|
||||
return nil, ArErr{
|
||||
"IndexError",
|
||||
@@ -51,7 +62,7 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
||||
true,
|
||||
}
|
||||
}
|
||||
if _, ok := m[key]; !ok {
|
||||
if _, ok := m.obj[key]; !ok {
|
||||
return nil, ArErr{
|
||||
"KeyError",
|
||||
"key '" + fmt.Sprint(key) + "' not found",
|
||||
@@ -61,12 +72,15 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
||||
true,
|
||||
}
|
||||
}
|
||||
return m[key], ArErr{}
|
||||
|
||||
case ArArray:
|
||||
return getFromArArray(m, r, stack, stacklevel)
|
||||
return potentialAnyArrayToArArray(m.obj[key]), ArErr{}
|
||||
case string:
|
||||
return getFromString(m, r, stack, stacklevel)
|
||||
if val, ok := r.args[0].(string); !r.index && ok {
|
||||
switch val {
|
||||
case "length":
|
||||
return len(m), ArErr{}
|
||||
}
|
||||
}
|
||||
return getFromString(m, r, stack, stacklevel+1)
|
||||
}
|
||||
|
||||
key, err := runVal(r.args[0], stack, stacklevel+1)
|
||||
@@ -84,9 +98,9 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
||||
}
|
||||
|
||||
func classVal(r any) any {
|
||||
if _, ok := r.(ArMap); ok {
|
||||
if _, ok := r.(ArMap)["__value__"]; ok {
|
||||
return r.(ArMap)["__value__"]
|
||||
if j, ok := r.(ArObject); ok {
|
||||
if _, ok := j.obj["__value__"]; ok {
|
||||
return j.obj["__value__"]
|
||||
}
|
||||
}
|
||||
return r
|
||||
@@ -105,7 +119,7 @@ func mapGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapGet
|
||||
if !worked {
|
||||
return ArMapGet{}, false, err, i
|
||||
}
|
||||
return ArMapGet{resp, ArArray{key}, false, code.line, code.realcode, code.path}, true, ArErr{}, 1
|
||||
return ArMapGet{resp, []any{key}, false, code.line, code.realcode, code.path}, true, ArErr{}, 1
|
||||
}
|
||||
|
||||
func isIndexGet(code UNPARSEcode) bool {
|
||||
@@ -126,7 +140,6 @@ func indexGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapG
|
||||
}
|
||||
continue
|
||||
}
|
||||
fmt.Println(args)
|
||||
if len(args) > 3 {
|
||||
return ArMapGet{}, false, ArErr{
|
||||
"SyntaxError",
|
||||
@@ -161,7 +174,7 @@ func isUnhashable(val any) bool {
|
||||
return keytype == "array" || keytype == "map"
|
||||
}
|
||||
|
||||
func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray, ArErr) {
|
||||
func getFromArArray(m ArObject, r ArMapGet, stack stack, stacklevel int) (ArObject, ArErr) {
|
||||
var (
|
||||
start int = 0
|
||||
end any = nil
|
||||
@@ -170,12 +183,12 @@ func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray,
|
||||
{
|
||||
startval, err := runVal(r.args[0], stack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
return ArObject{}, err
|
||||
}
|
||||
if startval == nil {
|
||||
start = 0
|
||||
} else if typeof(startval) != "number" && !startval.(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
} else if typeof(startval) != "number" || !startval.(number).IsInt() {
|
||||
return ArObject{}, ArErr{
|
||||
"TypeError",
|
||||
"slice index must be an integer",
|
||||
r.line,
|
||||
@@ -190,12 +203,12 @@ func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray,
|
||||
if len(r.args) > 1 {
|
||||
endval, err := runVal(r.args[1], stack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
return ArObject{}, err
|
||||
}
|
||||
if endval == nil {
|
||||
end = len(m)
|
||||
end = m.obj["length"]
|
||||
} else if typeof(endval) != "number" && !endval.(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
return ArObject{}, ArErr{
|
||||
"TypeError",
|
||||
"slice ending index must be an integer",
|
||||
r.line,
|
||||
@@ -210,12 +223,12 @@ func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray,
|
||||
if len(r.args) > 2 {
|
||||
stepval, err := runVal(r.args[2], stack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
return ArObject{}, err
|
||||
}
|
||||
if stepval == nil {
|
||||
step = 1
|
||||
} else if typeof(stepval) != "number" && !stepval.(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
return ArObject{}, ArErr{
|
||||
"TypeError",
|
||||
"slice step must be an integer",
|
||||
r.line,
|
||||
@@ -228,29 +241,27 @@ func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray,
|
||||
}
|
||||
}
|
||||
if start < 0 {
|
||||
start = len(m) + start
|
||||
start = m.obj["length"].(int) + start
|
||||
}
|
||||
if _, ok := end.(int); ok && end.(int) < 0 {
|
||||
end = len(m) + end.(int)
|
||||
end = m.obj["length"].(int) + end.(int)
|
||||
}
|
||||
|
||||
fmt.Println(start, end, step)
|
||||
if end == nil {
|
||||
return ArArray{m[start]}, ArErr{}
|
||||
return ArArray([]any{m.obj["__value__"].([]any)[start]}), ArErr{}
|
||||
} else if step == 1 {
|
||||
return m[start:end.(int)], ArErr{}
|
||||
return ArArray([]any{m.obj["__value__"].([]any)[start:end.(int)]}), ArErr{}
|
||||
} else {
|
||||
output := ArArray{}
|
||||
output := []any{}
|
||||
if step > 0 {
|
||||
for i := start; i < end.(int); i += step {
|
||||
output = append(output, m[i])
|
||||
output = append(output, m.obj["__value__"].([]any)[i])
|
||||
}
|
||||
} else {
|
||||
for i := end.(int) - 1; i >= start; i += step {
|
||||
output = append(output, m[i])
|
||||
output = append(output, m.obj["__value__"].([]any)[i])
|
||||
}
|
||||
}
|
||||
return (output), ArErr{}
|
||||
return ArArray(output), ArErr{}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +278,7 @@ func getFromString(m string, r ArMapGet, stack stack, stacklevel int) (string, A
|
||||
}
|
||||
if startval == nil {
|
||||
start = 0
|
||||
} else if typeof(startval) != "number" && !startval.(number).IsInt() {
|
||||
} else if typeof(startval) != "number" || !startval.(number).IsInt() {
|
||||
return "", ArErr{
|
||||
"TypeError",
|
||||
"slice index must be an integer",
|
||||
@@ -326,8 +337,6 @@ func getFromString(m string, r ArMapGet, stack stack, stacklevel int) (string, A
|
||||
if _, ok := end.(int); ok && end.(int) < 0 {
|
||||
end = len(m) + end.(int)
|
||||
}
|
||||
|
||||
fmt.Println(start, end, step)
|
||||
if end == nil {
|
||||
return string(m[start]), ArErr{}
|
||||
} else if step == 1 {
|
||||
|
||||
@@ -118,7 +118,7 @@ func parseIfStatement(code UNPARSEcode, index int, codeline []UNPARSEcode) (ifst
|
||||
|
||||
func runIfStatement(code ifstatement, stack stack, stacklevel int) (any, ArErr) {
|
||||
for _, condition := range code.conditions {
|
||||
newstack := append(stack, scope{})
|
||||
newstack := append(stack, newscope())
|
||||
resp, err := runVal(condition.condition, newstack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
@@ -128,7 +128,7 @@ func runIfStatement(code ifstatement, stack stack, stacklevel int) (any, ArErr)
|
||||
}
|
||||
}
|
||||
if code.ELSE != nil {
|
||||
return runVal(code.ELSE, append(stack, scope{}), stacklevel+1)
|
||||
return runVal(code.ELSE, append(stack, newscope()), stacklevel+1)
|
||||
}
|
||||
return nil, ArErr{}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var imported = make(map[string]ArObject)
|
||||
var importing = make(map[string]bool)
|
||||
|
||||
func FileExists(filename string) bool {
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
return true
|
||||
@@ -44,7 +47,7 @@ func readFile(path string) []UNPARSEcode {
|
||||
return output
|
||||
}
|
||||
|
||||
func importMod(realpath string, origin string) (scope, ArErr) {
|
||||
func importMod(realpath string, origin string, main bool) (ArObject, ArErr) {
|
||||
extention := filepath.Ext(realpath)
|
||||
path := realpath
|
||||
if extention == "" {
|
||||
@@ -52,13 +55,13 @@ func importMod(realpath string, origin string) (scope, ArErr) {
|
||||
}
|
||||
ex, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, ArErr{"Import Error", err.Error(), 0, realpath, "", true}
|
||||
return ArObject{}, ArErr{TYPE: "Import Error", message: "Could not get working directory", EXISTS: true}
|
||||
}
|
||||
executable, err := os.Executable()
|
||||
exc, err := os.Executable()
|
||||
if err != nil {
|
||||
return nil, ArErr{"Import Error", err.Error(), 0, realpath, "", true}
|
||||
return ArObject{}, ArErr{TYPE: "Import Error", message: "Could not get executable", EXISTS: true}
|
||||
}
|
||||
executable = filepath.Dir(executable)
|
||||
executable := filepath.Dir(exc)
|
||||
isABS := filepath.IsAbs(path)
|
||||
var pathsToTest []string
|
||||
if isABS {
|
||||
@@ -90,18 +93,52 @@ func importMod(realpath string, origin string) (scope, ArErr) {
|
||||
}
|
||||
|
||||
if !found {
|
||||
return nil, ArErr{"Import Error", "File does not exist: " + realpath, 0, realpath, "", true}
|
||||
return ArObject{}, ArErr{TYPE: "Import Error", message: "File does not exist: " + realpath, EXISTS: true}
|
||||
} else if importing[p] {
|
||||
return ArObject{}, ArErr{TYPE: "Import Error", message: "Circular import: " + realpath, EXISTS: true}
|
||||
} else if _, ok := imported[p]; ok {
|
||||
return imported[p], ArErr{}
|
||||
}
|
||||
importing[p] = true
|
||||
codelines := readFile(p)
|
||||
|
||||
translated, translationerr := translate(codelines)
|
||||
if translationerr.EXISTS {
|
||||
return nil, translationerr
|
||||
return ArObject{}, translationerr
|
||||
}
|
||||
global := scope{}
|
||||
_, runimeErr, _ := run(translated, stack{vars, global})
|
||||
ArgsArArray := []any{}
|
||||
for _, arg := range Args[1:] {
|
||||
ArgsArArray = append(ArgsArArray, arg)
|
||||
}
|
||||
global := newscope()
|
||||
localvars := Map(anymap{
|
||||
"program": Map(anymap{
|
||||
"args": ArArray(ArgsArArray),
|
||||
"origin": origin,
|
||||
"import": builtinFunc{"import", func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return nil, ArErr{"Import Error", "Invalid number of arguments", 0, realpath, "", true}
|
||||
}
|
||||
if _, ok := args[0].(string); !ok {
|
||||
return nil, ArErr{"Import Error", "Invalid argument type", 0, realpath, "", true}
|
||||
}
|
||||
return importMod(args[0].(string), filepath.Dir(p), false)
|
||||
}},
|
||||
"cwd": ex,
|
||||
"exc": exc,
|
||||
"file": Map(anymap{
|
||||
"name": filepath.Base(p),
|
||||
"path": p,
|
||||
}),
|
||||
"main": main,
|
||||
"scope": global,
|
||||
}),
|
||||
})
|
||||
_, runimeErr, _ := run(translated, stack{vars, localvars, global})
|
||||
importing[p] = false
|
||||
if runimeErr.EXISTS {
|
||||
return nil, runimeErr
|
||||
return ArObject{}, runimeErr
|
||||
}
|
||||
imported[p] = global
|
||||
return global, ArErr{}
|
||||
}
|
||||
|
||||
40
src/json.go
40
src/json.go
@@ -11,17 +11,13 @@ import (
|
||||
func convertToArgon(obj any) any {
|
||||
switch x := obj.(type) {
|
||||
case map[string]interface{}:
|
||||
newmap := ArMap{}
|
||||
newmap := Map(anymap{})
|
||||
for key, value := range x {
|
||||
newmap[key] = convertToArgon(value)
|
||||
newmap.obj[key] = convertToArgon(value)
|
||||
}
|
||||
return newmap
|
||||
case ArArray:
|
||||
newarray := ArArray{}
|
||||
for _, value := range x {
|
||||
newarray = append(newarray, convertToArgon(value))
|
||||
}
|
||||
return newarray
|
||||
case []any:
|
||||
return ArArray(x)
|
||||
case string:
|
||||
return x
|
||||
case float64:
|
||||
@@ -47,8 +43,18 @@ func jsonstringify(obj any, level int) (string, error) {
|
||||
output := []string{}
|
||||
obj = classVal(obj)
|
||||
switch x := obj.(type) {
|
||||
case ArMap:
|
||||
for key, value := range x {
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
for _, value := range x.obj["__value__"].([]any) {
|
||||
str, err := jsonstringify(value, level+1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
output = append(output, str)
|
||||
}
|
||||
return "[" + strings.Join(output, ", ") + "]", nil
|
||||
}
|
||||
for key, value := range x.obj {
|
||||
str, err := jsonstringify(value, level+1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -56,7 +62,7 @@ func jsonstringify(obj any, level int) (string, error) {
|
||||
output = append(output, ""+strconv.Quote(anyToArgon(key, false, true, 3, 0, false, 0))+": "+str)
|
||||
}
|
||||
return "{" + strings.Join(output, ", ") + "}", nil
|
||||
case ArArray:
|
||||
case []any:
|
||||
for _, value := range x {
|
||||
str, err := jsonstringify(value, level+1)
|
||||
if err != nil {
|
||||
@@ -82,24 +88,24 @@ func jsonstringify(obj any, level int) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var ArJSON = ArMap{
|
||||
var ArJSON = Map(anymap{
|
||||
"parse": builtinFunc{"parse", func(args ...any) (any, ArErr) {
|
||||
if len(args) == 0 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "parse takes 1 argument", EXISTS: true}
|
||||
return nil, ArErr{TYPE: "Runtime Error", message: "parse takes 1 argument", EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "string" {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "parse takes a string not a '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
return nil, ArErr{TYPE: "Runtime Error", message: "parse takes a string not a '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
}
|
||||
return jsonparse(args[0].(string)), ArErr{}
|
||||
}},
|
||||
"stringify": builtinFunc{"stringify", func(args ...any) (any, ArErr) {
|
||||
if len(args) == 0 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "stringify takes 1 argument", EXISTS: true}
|
||||
return nil, ArErr{TYPE: "Runtime Error", message: "stringify takes 1 argument", EXISTS: true}
|
||||
}
|
||||
str, err := jsonstringify(args[0], 0)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return nil, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return str, ArErr{}
|
||||
}},
|
||||
}
|
||||
})
|
||||
|
||||
12
src/main.go
12
src/main.go
@@ -7,8 +7,14 @@ import (
|
||||
// args without the program path
|
||||
var Args = os.Args[1:]
|
||||
|
||||
type scope = ArMap
|
||||
type stack = []scope
|
||||
type stack = []ArObject
|
||||
|
||||
func newscope() ArObject {
|
||||
return ArObject{
|
||||
TYPE: "map",
|
||||
obj: make(anymap),
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
ex, e := os.Getwd()
|
||||
@@ -19,7 +25,7 @@ func main() {
|
||||
shell()
|
||||
os.Exit(0)
|
||||
}
|
||||
_, err := importMod(Args[0], ex)
|
||||
_, err := importMod(Args[0], ex, true)
|
||||
if err.EXISTS {
|
||||
panicErr(err)
|
||||
os.Exit(1)
|
||||
|
||||
8
src/map.go
Normal file
8
src/map.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package main
|
||||
|
||||
func Map(val anymap) ArObject {
|
||||
return ArObject{
|
||||
TYPE: "map",
|
||||
obj: val,
|
||||
}
|
||||
}
|
||||
@@ -56,21 +56,30 @@ func runImport(importOBJ ArImport, stack stack, stacklevel int) (any, ArErr) {
|
||||
if e != nil {
|
||||
return nil, ArErr{"File Error", "could not get current working directory", importOBJ.line, importOBJ.path, importOBJ.code, true}
|
||||
}
|
||||
stackMap, err := importMod(path, ex)
|
||||
stackMap, err := importMod(path, ex, false)
|
||||
if err.EXISTS {
|
||||
if err.line == 0 {
|
||||
err.line = importOBJ.line
|
||||
}
|
||||
if err.path == "" {
|
||||
err.path = importOBJ.path
|
||||
}
|
||||
if err.code == "" {
|
||||
err.code = importOBJ.code
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
switch x := importOBJ.values.(type) {
|
||||
case []string:
|
||||
for _, v := range x {
|
||||
val, ok := stackMap[v]
|
||||
val, ok := stackMap.obj[v]
|
||||
if !ok {
|
||||
return nil, ArErr{"Import Error", "could not find value " + anyToArgon(v, true, false, 3, 0, false, 0) + " in module " + anyToArgon(path, true, false, 3, 0, false, 0), importOBJ.line, importOBJ.path, importOBJ.code, true}
|
||||
}
|
||||
stack[len(stack)-1][v] = val
|
||||
stack[len(stack)-1].obj[v] = val
|
||||
}
|
||||
case string:
|
||||
stack[len(stack)-1][x] = stackMap
|
||||
stack[len(stack)-1].obj[x] = stackMap
|
||||
}
|
||||
return nil, ArErr{}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func randomRange(args ...any) (any, ArErr) {
|
||||
return rand, ArErr{}
|
||||
}
|
||||
|
||||
var ArRandom = ArMap{
|
||||
var ArRandom = Map(anymap{
|
||||
"__call__": builtinFunc{"random", func(args ...any) (any, ArErr) {
|
||||
if len(args) != 0 {
|
||||
return nil, ArErr{
|
||||
@@ -68,7 +68,7 @@ var ArRandom = ArMap{
|
||||
return round(resp.(number), 0), ArErr{}
|
||||
}},
|
||||
"range": builtinFunc{"range", randomRange},
|
||||
}
|
||||
})
|
||||
|
||||
func init() {
|
||||
rand.Seed(
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func shell() {
|
||||
global := stack{vars, scope{}}
|
||||
global := stack{vars, newscope()}
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
go func() {
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var timing = ArMap{}
|
||||
var timing = anymap{}
|
||||
|
||||
var plain = ArMap{
|
||||
var plain = Map(anymap{
|
||||
"log": builtinFunc{"log", func(args ...any) (any, ArErr) {
|
||||
output := []any{}
|
||||
for i := 0; i < len(args); i++ {
|
||||
@@ -32,9 +32,9 @@ var plain = ArMap{
|
||||
fmt.Println(output...)
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
}
|
||||
})
|
||||
|
||||
var ArTerm = ArMap{
|
||||
var ArTerm = Map(anymap{
|
||||
"log": builtinFunc{"log", func(args ...any) (any, ArErr) {
|
||||
output := []any{}
|
||||
for i := 0; i < len(args); i++ {
|
||||
@@ -103,4 +103,4 @@ var ArTerm = ArMap{
|
||||
fmt.Printf("\x1b[%dm%s\x1b[0m", 34, fmt.Sprint(anyToArgon(id, false, true, 3, 0, false, 0), ": ", timesince)+"\n")
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
}
|
||||
})
|
||||
|
||||
@@ -17,11 +17,11 @@ func ArThread(args ...any) (any, ArErr) {
|
||||
}
|
||||
var resp any
|
||||
var err ArErr
|
||||
currentscope := stack{vars, scope{}}
|
||||
currentscope := stack{vars, newscope()}
|
||||
hasrun := false
|
||||
joined := false
|
||||
var wg sync.WaitGroup
|
||||
threaMap := ArMap{
|
||||
threadMap := Map(anymap{
|
||||
"start": builtinFunc{"start", func(args ...any) (any, ArErr) {
|
||||
if hasrun {
|
||||
return nil, ArErr{TYPE: "Runtime Error", message: "Cannot start a thread twice", EXISTS: true}
|
||||
@@ -44,6 +44,6 @@ func ArThread(args ...any) (any, ArErr) {
|
||||
wg.Wait()
|
||||
return resp, err
|
||||
}},
|
||||
}
|
||||
return threaMap, ArErr{}
|
||||
})
|
||||
return threadMap, ArErr{}
|
||||
}
|
||||
|
||||
10
src/time.go
10
src/time.go
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
var MicroSeconds = newNumber().SetInt64(1000000)
|
||||
|
||||
func ArTimeClass(N time.Time) ArMap {
|
||||
return ArMap{
|
||||
func ArTimeClass(N time.Time) ArObject {
|
||||
return Map(anymap{
|
||||
"__value__": newNumber().Quo(newNumber().SetInt64(N.UnixMicro()), MicroSeconds),
|
||||
"year": builtinFunc{
|
||||
"year",
|
||||
@@ -96,10 +96,10 @@ func ArTimeClass(N time.Time) ArMap {
|
||||
return N.Format(a[0].(string)), ArErr{}
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var ArTime = map[any]any{
|
||||
var ArTime = Map(anymap{
|
||||
"snooze": builtinFunc{"snooze", func(a ...any) (any, ArErr) {
|
||||
if len(a) > 0 {
|
||||
float, _ := a[0].(number).Float64()
|
||||
@@ -212,4 +212,4 @@ var ArTime = map[any]any{
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
@@ -72,17 +72,17 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
|
||||
if colored {
|
||||
output = append(output, "\x1b[0m")
|
||||
}
|
||||
case ArMap:
|
||||
if _, ok := x["__value__"]; ok {
|
||||
return anyToArgon(x["__value__"], quote, simplify, depth, indent, colored, plain)
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
return anyToArgon(x.obj["__value__"], quote, simplify, depth, indent, colored, plain)
|
||||
}
|
||||
if len(x) == 0 {
|
||||
if len(x.obj) == 0 {
|
||||
return "{}"
|
||||
}
|
||||
keys := make([]any, len(x))
|
||||
keys := make([]any, len(x.obj))
|
||||
|
||||
i := 0
|
||||
for k := range x {
|
||||
for k := range x.obj {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
@@ -103,13 +103,11 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
|
||||
}
|
||||
keyval = strings.Join(outputkeyval, "")
|
||||
}
|
||||
output = append(output, keyval+": "+anyToArgon(x[key], true, true, depth-1, indent+1, colored, plain))
|
||||
output = append(output, keyval+": "+anyToArgon(x.obj[key], true, true, depth-1, indent+1, colored, plain))
|
||||
}
|
||||
return "{" + maybenewline + (strings.Repeat(" ", (indent+1)*plain)) + strings.Join(output, ","+maybenewline+(strings.Repeat(" ", (indent+1)*plain))) + maybenewline + (strings.Repeat(" ", indent*plain)) + "}"
|
||||
case ArArray:
|
||||
if len(x) == 0 {
|
||||
return "[]"
|
||||
}
|
||||
case []any:
|
||||
singleline := len(x) <= 3
|
||||
output := []string{}
|
||||
if simplify && len(x) >= 100 {
|
||||
for i := 0; i < 10; i++ {
|
||||
@@ -128,9 +126,17 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
|
||||
} else {
|
||||
for i := 0; i < len(x); i++ {
|
||||
item := x[i]
|
||||
output = append(output, anyToArgon(item, true, true, depth-1, indent+1, colored, plain))
|
||||
converted := anyToArgon(item, true, true, depth-1, indent+1, colored, plain)
|
||||
if singleline && strings.Contains(converted, "\n") {
|
||||
singleline = false
|
||||
}
|
||||
output = append(output, converted)
|
||||
}
|
||||
}
|
||||
|
||||
if singleline {
|
||||
return "[" + strings.Join(output, ", ") + "]"
|
||||
}
|
||||
return "[" + maybenewline + (strings.Repeat(" ", (indent+1)*plain)) + strings.Join(output, ","+maybenewline+(strings.Repeat(" ", (indent+1)*plain))) + maybenewline + (strings.Repeat(" ", indent*plain)) + "]"
|
||||
case builtinFunc:
|
||||
if colored {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
func typeof(val any) string {
|
||||
switch val.(type) {
|
||||
switch x := val.(type) {
|
||||
case number:
|
||||
return "number"
|
||||
case string:
|
||||
@@ -14,10 +14,11 @@ func typeof(val any) string {
|
||||
return "function"
|
||||
case builtinFunc:
|
||||
return "function"
|
||||
case ArMap:
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
return "array"
|
||||
}
|
||||
return "map"
|
||||
case ArArray:
|
||||
return "array"
|
||||
case accessVariable:
|
||||
return "variable"
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ 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][v.name]
|
||||
val, ok := stack[i].obj[v.name]
|
||||
varMutex.RUnlock()
|
||||
if ok {
|
||||
return val, ArErr{}
|
||||
@@ -208,30 +208,30 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
|
||||
|
||||
if v.TYPE == "let" {
|
||||
varMutex.RLock()
|
||||
_, ok := stack[len(stack)-1][v.toset.(accessVariable).name]
|
||||
_, ok := stack[len(stack)-1].obj[v.toset.(accessVariable).name]
|
||||
varMutex.RUnlock()
|
||||
if ok {
|
||||
return nil, ArErr{"Runtime Error", "variable \"" + v.toset.(accessVariable).name + "\" already exists", v.line, v.path, v.code, true}
|
||||
}
|
||||
varMutex.Lock()
|
||||
stack[len(stack)-1][v.toset.(accessVariable).name] = resp
|
||||
stack[len(stack)-1].obj[v.toset.(accessVariable).name] = resp
|
||||
varMutex.Unlock()
|
||||
} else {
|
||||
switch x := v.toset.(type) {
|
||||
case accessVariable:
|
||||
for i := len(stack) - 1; i >= 0; i-- {
|
||||
varMutex.RLock()
|
||||
_, ok := stack[i][x.name]
|
||||
_, ok := stack[i].obj[x.name]
|
||||
varMutex.RUnlock()
|
||||
if ok {
|
||||
varMutex.Lock()
|
||||
stack[i][x.name] = resp
|
||||
stack[i].obj[x.name] = resp
|
||||
varMutex.Unlock()
|
||||
return ThrowOnNonLoop(resp, ArErr{})
|
||||
}
|
||||
}
|
||||
varMutex.Lock()
|
||||
stack[len(stack)-1][x.name] = resp
|
||||
stack[len(stack)-1].obj[x.name] = resp
|
||||
varMutex.Unlock()
|
||||
case ArMapGet:
|
||||
respp, err := runVal(x.VAL, stack, stacklevel+1)
|
||||
@@ -246,12 +246,12 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
|
||||
return nil, err
|
||||
}
|
||||
switch y := respp.(type) {
|
||||
case ArMap:
|
||||
case ArObject:
|
||||
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[key] = resp
|
||||
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}
|
||||
@@ -285,8 +285,8 @@ 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][x.name]; ok {
|
||||
delete(stack[i], x.name)
|
||||
if _, ok := stack[i].obj[x.name]; ok {
|
||||
delete(stack[i].obj, x.name)
|
||||
return nil, ArErr{}
|
||||
}
|
||||
}
|
||||
@@ -304,8 +304,14 @@ func runDelete(d ArDelete, stack stack, stacklevel int) (any, ArErr) {
|
||||
return nil, err
|
||||
}
|
||||
switch y := respp.(type) {
|
||||
case ArMap:
|
||||
delete(y, key)
|
||||
case ArObject:
|
||||
if y.TYPE == "array" {
|
||||
return nil, ArErr{"Runtime Error", "can't delete from array", d.line, d.path, d.code, true}
|
||||
}
|
||||
if isUnhashable(key) {
|
||||
return nil, ArErr{"Runtime Error", "can't use unhashable type as map key: " + typeof(key), d.line, d.path, d.code, true}
|
||||
}
|
||||
delete(y.obj, key)
|
||||
default:
|
||||
return nil, ArErr{"Runtime Error", "can't delete for non map", d.line, d.path, d.code, true}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user