mirror of
https://github.com/Open-Argon/argon-v3.git
synced 2025-12-06 08:56:07 +00:00
add while and forever loops
This commit is contained in:
13
go.mod
13
go.mod
@@ -2,4 +2,15 @@ module wbell.dev/m/v2
|
|||||||
|
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
require github.com/wadey/go-rounding v1.1.0
|
require (
|
||||||
|
github.com/fatih/color v1.14.1
|
||||||
|
github.com/wadey/go-rounding v1.1.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/jwalton/go-supportscolor v1.1.0 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||||
|
golang.org/x/sys v0.3.0 // indirect
|
||||||
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
|
||||||
|
)
|
||||||
|
|||||||
16
go.sum
16
go.sum
@@ -1,2 +1,18 @@
|
|||||||
|
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||||
|
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||||
|
github.com/jwalton/go-supportscolor v1.1.0 h1:HsXFJdMPjRUAx8cIW6g30hVSFYaxh9yRQwEWgkAR7lQ=
|
||||||
|
github.com/jwalton/go-supportscolor v1.1.0/go.mod h1:hFVUAZV2cWg+WFFC4v8pT2X/S2qUUBYMioBD9AINXGs=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||||
|
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/wadey/go-rounding v1.1.0 h1:RAs9dMkB/uUHFv9ljlbRFC8/kBrQ5jhwt1GQq+2cciY=
|
github.com/wadey/go-rounding v1.1.0 h1:RAs9dMkB/uUHFv9ljlbRFC8/kBrQ5jhwt1GQq+2cciY=
|
||||||
github.com/wadey/go-rounding v1.1.0/go.mod h1:/uD953tCL6Fea2Yp+LZBBp8d60QSObkMJxY6SPOJ5QE=
|
github.com/wadey/go-rounding v1.1.0/go.mod h1:/uD953tCL6Fea2Yp+LZBBp8d60QSObkMJxY6SPOJ5QE=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||||
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
||||||
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
func anyToBool(x any) bool {
|
|
||||||
switch x := x.(type) {
|
|
||||||
case string:
|
|
||||||
return x != ""
|
|
||||||
case number:
|
|
||||||
return x.Cmp(newNumber()) != 0
|
|
||||||
case bool:
|
|
||||||
return x
|
|
||||||
case nil:
|
|
||||||
return false
|
|
||||||
case ArMap:
|
|
||||||
return len(x) != 0
|
|
||||||
case builtinFunc:
|
|
||||||
return true
|
|
||||||
case Callable:
|
|
||||||
return true
|
|
||||||
case ArClass:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
42
src/boolean.go
Normal file
42
src/boolean.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
func anyToBool(x any) bool {
|
||||||
|
switch x := x.(type) {
|
||||||
|
case string:
|
||||||
|
return x != ""
|
||||||
|
case number:
|
||||||
|
return x.Cmp(newNumber()) != 0
|
||||||
|
case bool:
|
||||||
|
return x
|
||||||
|
case nil:
|
||||||
|
return false
|
||||||
|
case ArMap:
|
||||||
|
return len(x) != 0
|
||||||
|
case builtinFunc:
|
||||||
|
return true
|
||||||
|
case Callable:
|
||||||
|
return true
|
||||||
|
case ArClass:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var booleanCompile = makeRegex(`( )*(true|false|null)( )*`)
|
||||||
|
|
||||||
|
func isBoolean(code UNPARSEcode) bool {
|
||||||
|
return booleanCompile.MatchString(code.code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBoolean(code UNPARSEcode) (any, bool, ArErr, int) {
|
||||||
|
trim := strings.TrimSpace(code.code)
|
||||||
|
if trim == "true" {
|
||||||
|
return true, true, ArErr{}, 1
|
||||||
|
} else if trim == "false" {
|
||||||
|
return false, true, ArErr{}, 1
|
||||||
|
}
|
||||||
|
return nil, true, ArErr{}, 1
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ func ArgonNumber(args ...any) (any, ArErr) {
|
|||||||
}
|
}
|
||||||
switch x := args[0].(type) {
|
switch x := args[0].(type) {
|
||||||
case string:
|
case string:
|
||||||
if !numberCompile.MatchString(x) {
|
if !isNumber(UNPARSEcode{code: x}) {
|
||||||
return nil, ArErr{TYPE: "Conversion Error", message: "Cannot convert " + anyToArgon(x, true, true, 3, 0, false, 0) + " to a number", EXISTS: true}
|
return nil, ArErr{TYPE: "Conversion Error", message: "Cannot convert " + anyToArgon(x, true, true, 3, 0, false, 0) + " to a number", EXISTS: true}
|
||||||
}
|
}
|
||||||
N, _ := newNumber().SetString(x)
|
N, _ := newNumber().SetString(x)
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/wadey/go-rounding"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
var vars = scope{}
|
var vars = scope{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
vars["global"] = vars
|
vars["global"] = vars
|
||||||
vars["term"] = ArTerm
|
vars["term"] = ArTerm
|
||||||
vars["true"] = true
|
|
||||||
vars["false"] = false
|
|
||||||
vars["null"] = nil
|
|
||||||
vars["input"] = builtinFunc{"input", ArgonInput}
|
vars["input"] = builtinFunc{"input", ArgonInput}
|
||||||
vars["number"] = builtinFunc{"number", ArgonNumber}
|
vars["number"] = builtinFunc{"number", ArgonNumber}
|
||||||
vars["string"] = builtinFunc{"string", ArgonString}
|
vars["string"] = builtinFunc{"string", ArgonString}
|
||||||
@@ -36,9 +36,16 @@ func init() {
|
|||||||
newmap[i] = string(v)
|
newmap[i] = string(v)
|
||||||
}
|
}
|
||||||
return newmap, ArErr{}
|
return newmap, ArErr{}
|
||||||
case []any:
|
case ArArray:
|
||||||
newmap := ArMap{}
|
newmap := ArMap{}
|
||||||
for i, v := range x {
|
for i, v := range x {
|
||||||
|
switch y := v.(type) {
|
||||||
|
case ArArray:
|
||||||
|
if len(y) == 2 {
|
||||||
|
newmap[y[0]] = y[1]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
newmap[i] = v
|
newmap[i] = v
|
||||||
}
|
}
|
||||||
return newmap, ArErr{}
|
return newmap, ArErr{}
|
||||||
@@ -60,13 +67,19 @@ func init() {
|
|||||||
return newarray, ArErr{}
|
return newarray, ArErr{}
|
||||||
case ArMap:
|
case ArMap:
|
||||||
newarray := ArArray{}
|
newarray := ArArray{}
|
||||||
for _, v := range x {
|
for key, val := range x {
|
||||||
newarray = append(newarray, v)
|
newarray = append(newarray, ArArray{key, val})
|
||||||
}
|
}
|
||||||
return newarray, ArErr{}
|
return newarray, ArErr{}
|
||||||
}
|
}
|
||||||
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["boolean"] = builtinFunc{"boolean", func(a ...any) (any, ArErr) {
|
||||||
|
if len(a) == 0 {
|
||||||
|
return false, ArErr{}
|
||||||
|
}
|
||||||
|
return anyToBool(a[0]), ArErr{}
|
||||||
|
}}
|
||||||
vars["time"] = ArTime
|
vars["time"] = ArTime
|
||||||
vars["PI"] = PI
|
vars["PI"] = PI
|
||||||
vars["π"] = PI
|
vars["π"] = PI
|
||||||
@@ -95,7 +108,7 @@ func init() {
|
|||||||
|
|
||||||
switch x := a[0].(type) {
|
switch x := a[0].(type) {
|
||||||
case number:
|
case number:
|
||||||
return rounding.Round(newNumber().Set(x), int(precision.Num().Int64()), rounding.HalfUp), ArErr{}
|
return round(newNumber().Set(x), int(precision.Num().Int64())), ArErr{}
|
||||||
}
|
}
|
||||||
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}
|
||||||
}}
|
}}
|
||||||
@@ -106,11 +119,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
switch x := a[0].(type) {
|
switch x := a[0].(type) {
|
||||||
case number:
|
case number:
|
||||||
n := newNumber().Set(x)
|
return floor(x), ArErr{}
|
||||||
if n.Sign() < 0 {
|
|
||||||
return rounding.Round(n, 0, rounding.Up), ArErr{}
|
|
||||||
}
|
|
||||||
return rounding.Round(n, 0, rounding.Down), ArErr{}
|
|
||||||
}
|
}
|
||||||
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}
|
||||||
}}
|
}}
|
||||||
@@ -122,13 +131,36 @@ func init() {
|
|||||||
|
|
||||||
switch x := a[0].(type) {
|
switch x := a[0].(type) {
|
||||||
case number:
|
case number:
|
||||||
n := newNumber().Set(x)
|
return ceil(x), ArErr{}
|
||||||
if n.Sign() < 0 {
|
|
||||||
return rounding.Round(n, 0, rounding.Down), ArErr{}
|
|
||||||
}
|
|
||||||
return rounding.Round(n, 0, rounding.Up), ArErr{}
|
|
||||||
}
|
}
|
||||||
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["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["sqrt"] = builtinFunc{"sqrt", ArgonSqrt}
|
||||||
|
vars["random"] = ArRandom
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/call.go
16
src/call.go
@@ -67,6 +67,10 @@ func runCall(c call, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
if err.EXISTS {
|
if err.EXISTS {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
switch x := callable_.(type) {
|
||||||
|
case ArMap:
|
||||||
|
callable_ = x["__call__"]
|
||||||
|
}
|
||||||
callable = callable_
|
callable = callable_
|
||||||
}
|
}
|
||||||
args := []any{}
|
args := []any{}
|
||||||
@@ -82,7 +86,15 @@ func runCall(c call, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
case builtinFunc:
|
case builtinFunc:
|
||||||
resp, err := x.FUNC(args...)
|
resp, err := x.FUNC(args...)
|
||||||
if err.EXISTS {
|
if err.EXISTS {
|
||||||
err = ArErr{err.TYPE, err.message, c.line, c.path, c.code, true}
|
if err.line == 0 {
|
||||||
|
err.line = c.line
|
||||||
|
}
|
||||||
|
if err.path == "" {
|
||||||
|
err.path = c.path
|
||||||
|
}
|
||||||
|
if err.code == "" {
|
||||||
|
err.code = c.code
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return resp, err
|
return resp, err
|
||||||
case Callable:
|
case Callable:
|
||||||
@@ -94,7 +106,7 @@ func runCall(c call, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
level[param] = args[i]
|
level[param] = args[i]
|
||||||
}
|
}
|
||||||
resp, err := runVal(x.run, append(x.stack, level), stacklevel+1)
|
resp, err := runVal(x.run, append(x.stack, level), stacklevel+1)
|
||||||
return openJump(resp), err
|
return 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}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ func runDoWrap(d dowrap, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
switch x := val.(type) {
|
switch x := val.(type) {
|
||||||
case Return:
|
case Return:
|
||||||
return x, ArErr{}
|
return x, ArErr{}
|
||||||
|
case Break:
|
||||||
|
return x, ArErr{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, ArErr{}
|
return nil, ArErr{}
|
||||||
|
|||||||
134
src/ifstatement.go
Normal file
134
src/ifstatement.go
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ifstatmentCompile = makeRegex(`( *)if( )+\((.|\n)+\)( )+(.|\n)+`)
|
||||||
|
var elseifstatmentCompile = makeRegex(`( *)else( )+if( )+\((.|\n)+\)( )+(.|\n)+`)
|
||||||
|
var elseCompile = makeRegex(`( *)else( )+(.|\n)+`)
|
||||||
|
|
||||||
|
type statement struct {
|
||||||
|
condition any
|
||||||
|
THEN any
|
||||||
|
line int
|
||||||
|
code string
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ifstatement struct {
|
||||||
|
conditions []statement
|
||||||
|
ELSE any
|
||||||
|
line int
|
||||||
|
code string
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
func isIfStatement(code UNPARSEcode) bool {
|
||||||
|
return ifstatmentCompile.MatchString(code.code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseIfStatement(code UNPARSEcode, index int, codeline []UNPARSEcode) (ifstatement, bool, ArErr, int) {
|
||||||
|
conditions := []statement{}
|
||||||
|
var ELSE any
|
||||||
|
i := index
|
||||||
|
for i < len(codeline) && (elseifstatmentCompile.MatchString(codeline[i].code) || i == index) {
|
||||||
|
trimmed := strings.TrimSpace(codeline[i].code)
|
||||||
|
trimmed = strings.TrimSpace(trimmed[strings.Index(trimmed, "("):])
|
||||||
|
trimmed = (trimmed[1:])
|
||||||
|
split := strings.Split(trimmed, ")")
|
||||||
|
for j := len(split) - 1; j > 0; j-- {
|
||||||
|
conditionjoined := strings.Join(split[:j], ")")
|
||||||
|
thenjoined := strings.Join(split[j:], ")")
|
||||||
|
outindex := 0
|
||||||
|
conditionval, worked, err, step := translateVal(
|
||||||
|
UNPARSEcode{
|
||||||
|
code: conditionjoined,
|
||||||
|
realcode: codeline[i].realcode,
|
||||||
|
line: code.line,
|
||||||
|
path: code.path,
|
||||||
|
},
|
||||||
|
i,
|
||||||
|
codeline,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
if err.EXISTS || !worked {
|
||||||
|
if j == 1 {
|
||||||
|
return ifstatement{}, worked, err, step
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outindex += step
|
||||||
|
thenval, worked, err, step := translateVal(
|
||||||
|
UNPARSEcode{
|
||||||
|
code: thenjoined,
|
||||||
|
realcode: codeline[i].realcode,
|
||||||
|
line: code.line,
|
||||||
|
path: code.path,
|
||||||
|
},
|
||||||
|
i,
|
||||||
|
codeline,
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
if err.EXISTS || !worked {
|
||||||
|
return ifstatement{}, worked, err, step
|
||||||
|
}
|
||||||
|
outindex += step - 1
|
||||||
|
conditions = append(conditions, statement{
|
||||||
|
condition: conditionval,
|
||||||
|
THEN: thenval,
|
||||||
|
line: code.line,
|
||||||
|
code: code.realcode,
|
||||||
|
path: code.path,
|
||||||
|
})
|
||||||
|
i += outindex
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i < len(codeline) && elseCompile.MatchString(codeline[i].code) {
|
||||||
|
trimmed := strings.TrimSpace(codeline[i].code)
|
||||||
|
trimmed = strings.TrimSpace(trimmed[4:])
|
||||||
|
ELSEval, _, err, step := translateVal(
|
||||||
|
UNPARSEcode{
|
||||||
|
code: trimmed,
|
||||||
|
realcode: codeline[i].realcode,
|
||||||
|
line: code.line,
|
||||||
|
path: code.path,
|
||||||
|
},
|
||||||
|
i,
|
||||||
|
codeline,
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
if err.EXISTS {
|
||||||
|
return ifstatement{}, false, err, step
|
||||||
|
}
|
||||||
|
ELSE = ELSEval
|
||||||
|
i += step
|
||||||
|
}
|
||||||
|
return ifstatement{
|
||||||
|
conditions: conditions,
|
||||||
|
ELSE: ELSE,
|
||||||
|
line: code.line,
|
||||||
|
code: code.realcode,
|
||||||
|
path: code.path,
|
||||||
|
}, true, ArErr{}, i - index
|
||||||
|
}
|
||||||
|
|
||||||
|
func runIfStatement(code ifstatement, stack stack, stacklevel int) (any, ArErr) {
|
||||||
|
for _, condition := range code.conditions {
|
||||||
|
newstack := append(stack, scope{})
|
||||||
|
resp, err := runVal(condition.condition, newstack, stacklevel+1)
|
||||||
|
if err.EXISTS {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if anyToBool(resp) {
|
||||||
|
return runVal(condition.THEN, newstack, stacklevel+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if code.ELSE != nil {
|
||||||
|
return runVal(code.ELSE, append(stack, scope{}), stacklevel+1)
|
||||||
|
}
|
||||||
|
return nil, ArErr{}
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
package main
|
|
||||||
@@ -44,7 +44,7 @@ func readFile(path string) []UNPARSEcode {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
func importMod(realpath string, origin string, main bool) ArErr {
|
func importMod(realpath string, origin string, main bool) (scope, ArErr) {
|
||||||
extention := filepath.Ext(realpath)
|
extention := filepath.Ext(realpath)
|
||||||
path := realpath
|
path := realpath
|
||||||
if extention == "" {
|
if extention == "" {
|
||||||
@@ -52,11 +52,11 @@ func importMod(realpath string, origin string, main bool) ArErr {
|
|||||||
}
|
}
|
||||||
ex, err := os.Getwd()
|
ex, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ArErr{"Import Error", err.Error(), 0, realpath, "", true}
|
return nil, ArErr{"Import Error", err.Error(), 0, realpath, "", true}
|
||||||
}
|
}
|
||||||
executable, err := os.Executable()
|
executable, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ArErr{"Import Error", err.Error(), 0, realpath, "", true}
|
return nil, ArErr{"Import Error", err.Error(), 0, realpath, "", true}
|
||||||
}
|
}
|
||||||
executable = filepath.Dir(executable)
|
executable = filepath.Dir(executable)
|
||||||
isABS := filepath.IsAbs(path)
|
isABS := filepath.IsAbs(path)
|
||||||
@@ -90,18 +90,18 @@ func importMod(realpath string, origin string, main bool) ArErr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
return ArErr{"Import Error", "File does not exist: " + realpath, 0, realpath, "", true}
|
return nil, ArErr{"Import Error", "File does not exist: " + realpath, 0, realpath, "", true}
|
||||||
}
|
}
|
||||||
codelines := readFile(p)
|
codelines := readFile(p)
|
||||||
|
|
||||||
translated, translationerr := translate(codelines)
|
translated, translationerr := translate(codelines)
|
||||||
if translationerr.EXISTS {
|
if translationerr.EXISTS {
|
||||||
return translationerr
|
return nil, translationerr
|
||||||
}
|
}
|
||||||
global := scope{}
|
global := scope{}
|
||||||
_, runimeErr, _ := run(translated, stack{vars, global})
|
_, runimeErr, _ := run(translated, stack{vars, global})
|
||||||
if runimeErr.EXISTS {
|
if runimeErr.EXISTS {
|
||||||
return runimeErr
|
return nil, runimeErr
|
||||||
}
|
}
|
||||||
return ArErr{}
|
return global, ArErr{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
var returnCompile = makeRegex(`( *)return( +)(.|\n)+`)
|
var returnCompile = makeRegex(`( *)return( +)(.|\n)+`)
|
||||||
|
var breakCompile = makeRegex(`( *)break( *)`)
|
||||||
|
|
||||||
type CallReturn struct {
|
type CallReturn struct {
|
||||||
value any
|
value any
|
||||||
@@ -18,10 +21,25 @@ type Return struct {
|
|||||||
path string
|
path string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CallBreak struct {
|
||||||
|
line int
|
||||||
|
code string
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
type Break struct {
|
||||||
|
line int
|
||||||
|
code string
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
func isReturn(code UNPARSEcode) bool {
|
func isReturn(code UNPARSEcode) bool {
|
||||||
return returnCompile.MatchString(code.code)
|
return returnCompile.MatchString(code.code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isBreak(code UNPARSEcode) bool {
|
||||||
|
return breakCompile.MatchString(code.code)
|
||||||
|
}
|
||||||
|
|
||||||
func parseReturn(code UNPARSEcode, index int, codeline []UNPARSEcode) (CallReturn, bool, ArErr, int) {
|
func parseReturn(code UNPARSEcode, index int, codeline []UNPARSEcode) (CallReturn, bool, ArErr, int) {
|
||||||
resp, worked, err, i := translateVal(UNPARSEcode{
|
resp, worked, err, i := translateVal(UNPARSEcode{
|
||||||
code: strings.TrimSpace(code.code)[6:],
|
code: strings.TrimSpace(code.code)[6:],
|
||||||
@@ -54,7 +72,7 @@ func runReturn(code CallReturn, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
}, ArErr{}
|
}, ArErr{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func openJump(resp any) any {
|
func openReturn(resp any) any {
|
||||||
switch x := resp.(type) {
|
switch x := resp.(type) {
|
||||||
case Return:
|
case Return:
|
||||||
return x.value
|
return x.value
|
||||||
@@ -62,3 +80,19 @@ func openJump(resp any) any {
|
|||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseBreak(code UNPARSEcode, index int, codeline []UNPARSEcode) (CallBreak, bool, ArErr, int) {
|
||||||
|
return CallBreak{
|
||||||
|
line: code.line,
|
||||||
|
code: code.realcode,
|
||||||
|
path: code.path,
|
||||||
|
}, true, ArErr{}, 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func runBreak(code CallBreak, stack stack, stacklevel int) (any, ArErr) {
|
||||||
|
return Break{
|
||||||
|
line: code.line,
|
||||||
|
code: code.code,
|
||||||
|
path: code.path,
|
||||||
|
}, ArErr{}
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ func main() {
|
|||||||
shell()
|
shell()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
err := importMod(Args[0], ex, true)
|
_, err := importMod(Args[0], ex, true)
|
||||||
if err.EXISTS {
|
if err.EXISTS {
|
||||||
panicErr(err)
|
panicErr(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
startindex := 0
|
startindex := 0
|
||||||
endindex := 1
|
endindex := 1
|
||||||
step := 1
|
step := 1
|
||||||
|
slice := false
|
||||||
|
|
||||||
if !r.index {
|
if !r.index {
|
||||||
key, err := runVal(r.start, stack, stacklevel+1)
|
key, err := runVal(r.start, stack, stacklevel+1)
|
||||||
@@ -72,7 +73,15 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if key == "length" {
|
if key == "length" {
|
||||||
return len(m), ArErr{}
|
return newNumber().SetInt64(int64(len(m))), ArErr{}
|
||||||
|
}
|
||||||
|
return nil, ArErr{
|
||||||
|
"IndexError",
|
||||||
|
"index not found",
|
||||||
|
r.line,
|
||||||
|
r.path,
|
||||||
|
r.code,
|
||||||
|
true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if r.start != nil {
|
if r.start != nil {
|
||||||
@@ -119,6 +128,7 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
true,
|
true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
slice = true
|
||||||
num := eindex.(number)
|
num := eindex.(number)
|
||||||
if !num.IsInt() {
|
if !num.IsInt() {
|
||||||
return nil, ArErr{
|
return nil, ArErr{
|
||||||
@@ -149,6 +159,7 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
true,
|
true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
slice = true
|
||||||
num := step.(number)
|
num := step.(number)
|
||||||
if !num.IsInt() {
|
if !num.IsInt() {
|
||||||
return nil, ArErr{
|
return nil, ArErr{
|
||||||
@@ -202,6 +213,9 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
true,
|
true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !slice {
|
||||||
|
return m[startindex], ArErr{}
|
||||||
|
}
|
||||||
return m[startindex:endindex:step], ArErr{}
|
return m[startindex:endindex:step], ArErr{}
|
||||||
case ArClass:
|
case ArClass:
|
||||||
if r.numberofindex > 1 {
|
if r.numberofindex > 1 {
|
||||||
@@ -240,7 +254,7 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if key == "length" {
|
if key == "length" {
|
||||||
return len(m), ArErr{}
|
return newNumber().SetInt64(int64(len(m))), ArErr{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if r.start != nil {
|
if r.start != nil {
|
||||||
|
|||||||
77
src/random.go
Normal file
77
src/random.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func random() number {
|
||||||
|
return newNumber().SetFloat64(
|
||||||
|
rand.Float64(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomRange(args ...any) (any, ArErr) {
|
||||||
|
if len(args) != 2 {
|
||||||
|
return nil, ArErr{
|
||||||
|
TYPE: "Runtime Error",
|
||||||
|
message: "takes 2 arguments, got " + fmt.Sprint(len(args)),
|
||||||
|
EXISTS: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if typeof(args[0]) != "number" {
|
||||||
|
return nil, ArErr{
|
||||||
|
TYPE: "Runtime Error",
|
||||||
|
message: "takes a number not a '" + typeof(args[0]) + "'",
|
||||||
|
EXISTS: true,
|
||||||
|
}
|
||||||
|
} else if typeof(args[1]) != "number" {
|
||||||
|
return nil, ArErr{
|
||||||
|
TYPE: "Runtime Error",
|
||||||
|
message: "takes a number not a '" + typeof(args[1]) + "'",
|
||||||
|
EXISTS: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
min := args[0].(number)
|
||||||
|
max := args[1].(number)
|
||||||
|
if min.Cmp(max) > 0 {
|
||||||
|
return nil, ArErr{
|
||||||
|
TYPE: "Runtime Error",
|
||||||
|
message: "takes a min less than max",
|
||||||
|
EXISTS: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
difference := newNumber().Sub(max, min)
|
||||||
|
rand := random()
|
||||||
|
rand.Mul(rand, difference)
|
||||||
|
rand.Add(rand, min)
|
||||||
|
return rand, ArErr{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ArRandom = ArMap{
|
||||||
|
"__call__": builtinFunc{"random", func(args ...any) (any, ArErr) {
|
||||||
|
if len(args) != 0 {
|
||||||
|
return nil, ArErr{
|
||||||
|
TYPE: "Runtime Error",
|
||||||
|
message: "takes 0 arguments, got " + fmt.Sprint(len(args)),
|
||||||
|
EXISTS: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return random(), ArErr{}
|
||||||
|
}},
|
||||||
|
"int": builtinFunc{"int", func(a ...any) (any, ArErr) {
|
||||||
|
resp, err := randomRange(a...)
|
||||||
|
if err.EXISTS {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return round(resp.(number), 0), ArErr{}
|
||||||
|
}},
|
||||||
|
"range": builtinFunc{"range", randomRange},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Seed(
|
||||||
|
time.Now().UnixMicro(),
|
||||||
|
)
|
||||||
|
}
|
||||||
24
src/rounding.go
Normal file
24
src/rounding.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/wadey/go-rounding"
|
||||||
|
|
||||||
|
func floor(x number) number {
|
||||||
|
|
||||||
|
n := newNumber().Set(x)
|
||||||
|
if n.Sign() < 0 {
|
||||||
|
return rounding.Round(n, 0, rounding.Up)
|
||||||
|
}
|
||||||
|
return rounding.Round(n, 0, rounding.Down)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ceil(x number) number {
|
||||||
|
n := newNumber().Set(x)
|
||||||
|
if n.Sign() < 0 {
|
||||||
|
return rounding.Round(n, 0, rounding.Down)
|
||||||
|
}
|
||||||
|
return rounding.Round(n, 0, rounding.Up)
|
||||||
|
}
|
||||||
|
|
||||||
|
func round(x number, precision int) number {
|
||||||
|
return rounding.Round(newNumber().Set(x), precision, rounding.HalfUp)
|
||||||
|
}
|
||||||
10
src/run.go
10
src/run.go
@@ -57,10 +57,20 @@ func runVal(line any, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
return runDoWrap(x, stack, stacklevel+1)
|
return runDoWrap(x, stack, stacklevel+1)
|
||||||
case CallReturn:
|
case CallReturn:
|
||||||
return runReturn(x, stack, stacklevel+1)
|
return runReturn(x, stack, stacklevel+1)
|
||||||
|
case CallBreak:
|
||||||
|
return runBreak(x, stack, stacklevel+1)
|
||||||
case ArDelete:
|
case ArDelete:
|
||||||
return runDelete(x, stack, stacklevel+1)
|
return runDelete(x, stack, stacklevel+1)
|
||||||
case not:
|
case not:
|
||||||
return runNot(x, stack, stacklevel+1)
|
return runNot(x, stack, stacklevel+1)
|
||||||
|
case ifstatement:
|
||||||
|
return runIfStatement(x, stack, stacklevel+1)
|
||||||
|
case whileLoop:
|
||||||
|
return runWhileLoop(x, stack, stacklevel+1)
|
||||||
|
case bool:
|
||||||
|
return x, ArErr{}
|
||||||
|
case nil:
|
||||||
|
return nil, ArErr{}
|
||||||
}
|
}
|
||||||
fmt.Println("unreachable", reflect.TypeOf(line))
|
fmt.Println("unreachable", reflect.TypeOf(line))
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
|
|||||||
@@ -29,9 +29,10 @@ func shell() {
|
|||||||
totranslate := []UNPARSEcode{}
|
totranslate := []UNPARSEcode{}
|
||||||
code := input("\x1b[38;5;240m>>> \x1b[0m\x1b[1;5;240m")
|
code := input("\x1b[38;5;240m>>> \x1b[0m\x1b[1;5;240m")
|
||||||
fmt.Print("\x1b[0m")
|
fmt.Print("\x1b[0m")
|
||||||
if isEndingWithDo(code) {
|
if code == "" {
|
||||||
indo = true
|
continue
|
||||||
}
|
}
|
||||||
|
indo = true
|
||||||
totranslate = append(totranslate, UNPARSEcode{code, code, 1, "<shell>"})
|
totranslate = append(totranslate, UNPARSEcode{code, code, 1, "<shell>"})
|
||||||
for i := 2; indo; i++ {
|
for i := 2; indo; i++ {
|
||||||
code := input("\x1b[38;5;240m... \x1b[0m\x1b[1;5;240m")
|
code := input("\x1b[38;5;240m... \x1b[0m\x1b[1;5;240m")
|
||||||
@@ -49,8 +50,7 @@ func shell() {
|
|||||||
_, runimeErr, output := run(translated, global)
|
_, runimeErr, output := run(translated, global)
|
||||||
if runimeErr.EXISTS {
|
if runimeErr.EXISTS {
|
||||||
panicErr(runimeErr)
|
panicErr(runimeErr)
|
||||||
}
|
} else if count == 1 {
|
||||||
if count == 1 {
|
|
||||||
fmt.Println(anyToArgon(output, true, true, 3, 0, true, 1))
|
fmt.Println(anyToArgon(output, true, true, 3, 0, true, 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,21 +5,25 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
|
"github.com/jwalton/go-supportscolor"
|
||||||
)
|
)
|
||||||
|
|
||||||
func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, color bool, plain int) string {
|
func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored bool, plain int) string {
|
||||||
output := []string{}
|
output := []string{}
|
||||||
maybenewline := ""
|
maybenewline := ""
|
||||||
if plain == 1 {
|
if plain == 1 {
|
||||||
maybenewline = "\n"
|
maybenewline = "\n"
|
||||||
}
|
}
|
||||||
if depth == 0 {
|
if colored {
|
||||||
if color {
|
colored = supportscolor.Stdout().SupportsColor
|
||||||
output = append(output, "\x1b[38;5;240m")
|
|
||||||
}
|
}
|
||||||
|
if depth == 0 {
|
||||||
|
if colored {
|
||||||
|
output = append(output, color.New(38).Sprint("(...)"))
|
||||||
|
} else {
|
||||||
output = append(output, "(...)")
|
output = append(output, "(...)")
|
||||||
if color {
|
|
||||||
output = append(output, "\x1b[0m")
|
|
||||||
}
|
}
|
||||||
return strings.Join(output, "")
|
return strings.Join(output, "")
|
||||||
}
|
}
|
||||||
@@ -29,15 +33,14 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, color b
|
|||||||
output = append(output, x)
|
output = append(output, x)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if color {
|
quoted := strconv.Quote(x)
|
||||||
output = append(output, "\x1b[33;5;240m")
|
if colored {
|
||||||
}
|
output = append(output, color.New(33).Sprint(quoted))
|
||||||
output = append(output, strconv.Quote(x))
|
} else {
|
||||||
if color {
|
output = append(output, quoted)
|
||||||
output = append(output, "\x1b[0m")
|
|
||||||
}
|
}
|
||||||
case number:
|
case number:
|
||||||
if color {
|
if colored {
|
||||||
output = append(output, "\x1b[34;5;240m")
|
output = append(output, "\x1b[34;5;240m")
|
||||||
}
|
}
|
||||||
num, _ := x.Float64()
|
num, _ := x.Float64()
|
||||||
@@ -50,23 +53,23 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, color b
|
|||||||
} else {
|
} else {
|
||||||
output = append(output, numberToString(x, simplify))
|
output = append(output, numberToString(x, simplify))
|
||||||
}
|
}
|
||||||
if color {
|
if colored {
|
||||||
output = append(output, "\x1b[0m")
|
output = append(output, "\x1b[0m")
|
||||||
}
|
}
|
||||||
case bool:
|
case bool:
|
||||||
if color {
|
if colored {
|
||||||
output = append(output, "\x1b[35;5;240m")
|
output = append(output, "\x1b[35;5;240m")
|
||||||
}
|
}
|
||||||
output = append(output, strconv.FormatBool(x))
|
output = append(output, strconv.FormatBool(x))
|
||||||
if color {
|
if colored {
|
||||||
output = append(output, "\x1b[0m")
|
output = append(output, "\x1b[0m")
|
||||||
}
|
}
|
||||||
case nil:
|
case nil:
|
||||||
if color {
|
if colored {
|
||||||
output = append(output, "\x1b[31;5;240m")
|
output = append(output, "\x1b[31;5;240m")
|
||||||
}
|
}
|
||||||
output = append(output, "null")
|
output = append(output, "null")
|
||||||
if color {
|
if colored {
|
||||||
output = append(output, "\x1b[0m")
|
output = append(output, "\x1b[0m")
|
||||||
}
|
}
|
||||||
case ArMap:
|
case ArMap:
|
||||||
@@ -82,7 +85,7 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, color b
|
|||||||
}
|
}
|
||||||
output := []string{}
|
output := []string{}
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
output = append(output, anyToArgon(key, true, true, depth, (indent+1)*plain, color, plain)+": "+anyToArgon(x[key], true, true, depth-1, indent+1, color, plain))
|
output = append(output, anyToArgon(key, true, true, depth, (indent+1)*plain, colored, plain)+": "+anyToArgon(x[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)) + "}"
|
return "{" + maybenewline + (strings.Repeat(" ", (indent+1)*plain)) + strings.Join(output, ","+maybenewline+(strings.Repeat(" ", (indent+1)*plain))) + maybenewline + (strings.Repeat(" ", indent*plain)) + "}"
|
||||||
case ArArray:
|
case ArArray:
|
||||||
@@ -93,42 +96,42 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, color b
|
|||||||
if simplify && len(x) >= 100 {
|
if simplify && len(x) >= 100 {
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
item := x[i]
|
item := x[i]
|
||||||
output = append(output, anyToArgon(item, true, true, depth-1, indent+1, color, plain))
|
output = append(output, anyToArgon(item, true, true, depth-1, indent+1, colored, plain))
|
||||||
}
|
}
|
||||||
if color {
|
if colored {
|
||||||
output = append(output, "\x1b[38;5;240m(...)\x1b[0m")
|
output = append(output, "\x1b[38;5;240m(...)\x1b[0m")
|
||||||
} else {
|
} else {
|
||||||
output = append(output, "(...)")
|
output = append(output, "(...)")
|
||||||
}
|
}
|
||||||
for i := len(x) - 10; i < len(x); i++ {
|
for i := len(x) - 10; i < len(x); i++ {
|
||||||
item := x[i]
|
item := x[i]
|
||||||
output = append(output, anyToArgon(item, true, true, depth-1, indent+1, color, plain))
|
output = append(output, anyToArgon(item, true, true, depth-1, indent+1, colored, plain))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i := 0; i < len(x); i++ {
|
for i := 0; i < len(x); i++ {
|
||||||
item := x[i]
|
item := x[i]
|
||||||
output = append(output, anyToArgon(item, true, true, depth-1, indent+1, color, plain))
|
output = append(output, anyToArgon(item, 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)) + "]"
|
return "[" + maybenewline + (strings.Repeat(" ", (indent+1)*plain)) + strings.Join(output, ","+maybenewline+(strings.Repeat(" ", (indent+1)*plain))) + maybenewline + (strings.Repeat(" ", indent*plain)) + "]"
|
||||||
case builtinFunc:
|
case builtinFunc:
|
||||||
if color {
|
if colored {
|
||||||
output = append(output, "\x1b[38;5;240m")
|
output = append(output, "\x1b[38;5;240m")
|
||||||
}
|
}
|
||||||
output = append(output, "<builtin function "+x.name+">")
|
output = append(output, "<builtin function "+x.name+">")
|
||||||
if color {
|
if colored {
|
||||||
output = append(output, "\x1b[0m")
|
output = append(output, "\x1b[0m")
|
||||||
}
|
}
|
||||||
case Callable:
|
case Callable:
|
||||||
if color {
|
if colored {
|
||||||
output = append(output, "\x1b[38;5;240m")
|
output = append(output, "\x1b[38;5;240m")
|
||||||
}
|
}
|
||||||
output = append(output, "<function>")
|
output = append(output, "<function>")
|
||||||
if color {
|
if colored {
|
||||||
output = append(output, "\x1b[0m")
|
output = append(output, "\x1b[0m")
|
||||||
}
|
}
|
||||||
case ArClass:
|
case ArClass:
|
||||||
return anyToArgon(x.value, quote, simplify, depth, indent, color, plain)
|
return anyToArgon(x.value, quote, simplify, depth, indent, colored, plain)
|
||||||
default:
|
default:
|
||||||
return fmt.Sprint(x)
|
return fmt.Sprint(x)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
type UNPARSEcode struct {
|
type UNPARSEcode struct {
|
||||||
code string
|
code string
|
||||||
@@ -22,6 +24,14 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i
|
|||||||
}
|
}
|
||||||
} else if isReturn(code) {
|
} else if isReturn(code) {
|
||||||
return parseReturn(code, index, codelines)
|
return parseReturn(code, index, codelines)
|
||||||
|
} else if isBreak(code) {
|
||||||
|
return parseBreak(code, index, codelines)
|
||||||
|
} else if isIfStatement(code) {
|
||||||
|
return parseIfStatement(code, index, codelines)
|
||||||
|
} else if isWhileLoop(code) {
|
||||||
|
return parseWhileLoop(code, index, codelines)
|
||||||
|
} else if isForeverLoop(code) {
|
||||||
|
return parseForeverLoop(code, index, codelines)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +83,9 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i
|
|||||||
return call, worked, err, step
|
return call, worked, err, step
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isVariable(code) {
|
if isBoolean(code) {
|
||||||
|
return parseBoolean(code)
|
||||||
|
} else if isVariable(code) {
|
||||||
return parseVariable(code)
|
return parseVariable(code)
|
||||||
} else if isMapGet(code) {
|
} else if isMapGet(code) {
|
||||||
return mapGetParse(code, index, codelines)
|
return mapGetParse(code, index, codelines)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
var variableCompile = makeRegex(`( *)([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*( *)`)
|
var variableCompile = makeRegex(`( *)([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*( *)`)
|
||||||
@@ -10,6 +11,8 @@ 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,
|
||||||
@@ -73,7 +76,10 @@ 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-- {
|
||||||
if val, ok := stack[i][v.name]; ok {
|
varMutex.RLock()
|
||||||
|
val, ok := stack[i][v.name]
|
||||||
|
varMutex.RUnlock()
|
||||||
|
if ok {
|
||||||
return val, ArErr{}
|
return val, ArErr{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,24 +202,36 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
if err.EXISTS {
|
if err.EXISTS {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
resp = openJump(respp)
|
resp = openReturn(respp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.TYPE == "let" {
|
if v.TYPE == "let" {
|
||||||
if _, ok := stack[len(stack)-1][v.toset.(accessVariable).name]; ok {
|
varMutex.RLock()
|
||||||
|
_, ok := stack[len(stack)-1][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}
|
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][v.toset.(accessVariable).name] = resp
|
||||||
|
varMutex.Unlock()
|
||||||
} else {
|
} else {
|
||||||
switch x := v.toset.(type) {
|
switch x := v.toset.(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][x.name]; ok {
|
varMutex.RLock()
|
||||||
|
_, ok := stack[i][x.name]
|
||||||
|
varMutex.RUnlock()
|
||||||
|
if ok {
|
||||||
|
varMutex.Lock()
|
||||||
stack[i][x.name] = resp
|
stack[i][x.name] = resp
|
||||||
|
varMutex.Unlock()
|
||||||
return resp, ArErr{}
|
return resp, ArErr{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
varMutex.Lock()
|
||||||
stack[len(stack)-1][x.name] = resp
|
stack[len(stack)-1][x.name] = resp
|
||||||
|
varMutex.Unlock()
|
||||||
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 {
|
||||||
@@ -225,7 +243,9 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
|
|||||||
}
|
}
|
||||||
switch y := respp.(type) {
|
switch y := respp.(type) {
|
||||||
case ArMap:
|
case ArMap:
|
||||||
|
varMutex.Lock()
|
||||||
y[key] = resp
|
y[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 map", v.line, v.path, v.code, true}
|
||||||
}
|
}
|
||||||
|
|||||||
131
src/whileloop.go
Normal file
131
src/whileloop.go
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var whileLoopCompiled = makeRegex(`( *)while( )+\((.|\n)+\)( )+(.|\n)+`)
|
||||||
|
var foreverLoopCompiled = makeRegex(`( *)forever( )+(.|\n)+`)
|
||||||
|
|
||||||
|
type whileLoop struct {
|
||||||
|
condition any
|
||||||
|
body any
|
||||||
|
line int
|
||||||
|
code string
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
func isWhileLoop(code UNPARSEcode) bool {
|
||||||
|
return whileLoopCompiled.MatchString(code.code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isForeverLoop(code UNPARSEcode) bool {
|
||||||
|
return foreverLoopCompiled.MatchString(code.code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseWhileLoop(code UNPARSEcode, index int, codeline []UNPARSEcode) (whileLoop, bool, ArErr, int) {
|
||||||
|
trimmed := strings.TrimSpace(code.code)
|
||||||
|
trimmed = strings.TrimSpace(trimmed[strings.Index(trimmed, "("):])
|
||||||
|
trimmed = (trimmed[1:])
|
||||||
|
split := strings.Split(trimmed, ")")
|
||||||
|
for j := len(split) - 1; j > 0; j-- {
|
||||||
|
conditionjoined := strings.Join(split[:j], ")")
|
||||||
|
thenjoined := strings.Join(split[j:], ")")
|
||||||
|
outindex := 0
|
||||||
|
conditionval, worked, err, step := translateVal(
|
||||||
|
UNPARSEcode{
|
||||||
|
code: conditionjoined,
|
||||||
|
realcode: code.realcode,
|
||||||
|
line: code.line,
|
||||||
|
path: code.path,
|
||||||
|
},
|
||||||
|
index,
|
||||||
|
codeline,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
if err.EXISTS || !worked {
|
||||||
|
if j == 1 {
|
||||||
|
return whileLoop{}, worked, err, step
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outindex += step
|
||||||
|
thenval, worked, err, step := translateVal(
|
||||||
|
UNPARSEcode{
|
||||||
|
code: thenjoined,
|
||||||
|
realcode: code.realcode,
|
||||||
|
line: code.line,
|
||||||
|
path: code.path,
|
||||||
|
},
|
||||||
|
index+outindex-1,
|
||||||
|
codeline,
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
if err.EXISTS || !worked {
|
||||||
|
return whileLoop{}, worked, err, step
|
||||||
|
}
|
||||||
|
outindex += step - 1
|
||||||
|
return whileLoop{
|
||||||
|
condition: conditionval,
|
||||||
|
body: thenval,
|
||||||
|
line: code.line,
|
||||||
|
code: code.realcode,
|
||||||
|
path: code.path,
|
||||||
|
}, true, ArErr{}, outindex
|
||||||
|
}
|
||||||
|
return whileLoop{}, false, ArErr{
|
||||||
|
"Syntax Error",
|
||||||
|
"Could not parse while loop",
|
||||||
|
code.line,
|
||||||
|
code.path,
|
||||||
|
code.realcode,
|
||||||
|
true,
|
||||||
|
}, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseForeverLoop(code UNPARSEcode, index int, codeline []UNPARSEcode) (whileLoop, bool, ArErr, int) {
|
||||||
|
trimmed := strings.TrimSpace(code.code)
|
||||||
|
trimmed = strings.TrimSpace(trimmed[7:])
|
||||||
|
thenval, worked, err, step := translateVal(
|
||||||
|
UNPARSEcode{
|
||||||
|
code: trimmed,
|
||||||
|
realcode: code.realcode,
|
||||||
|
line: code.line,
|
||||||
|
path: code.path,
|
||||||
|
},
|
||||||
|
index,
|
||||||
|
codeline,
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
return whileLoop{
|
||||||
|
condition: true,
|
||||||
|
body: thenval,
|
||||||
|
line: code.line,
|
||||||
|
code: code.realcode,
|
||||||
|
path: code.path,
|
||||||
|
}, worked, err, step
|
||||||
|
}
|
||||||
|
|
||||||
|
func runWhileLoop(loop whileLoop, stack stack, stacklevel int) (any, ArErr) {
|
||||||
|
for {
|
||||||
|
condition, err := runVal(loop.condition, stack, stacklevel+1)
|
||||||
|
if err.EXISTS {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !anyToBool(condition) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
resp, err := runVal(loop.body, stack, stacklevel+1)
|
||||||
|
if err.EXISTS {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
switch x := resp.(type) {
|
||||||
|
case Return:
|
||||||
|
return x, ArErr{}
|
||||||
|
case Break:
|
||||||
|
return nil, ArErr{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, ArErr{}
|
||||||
|
}
|
||||||
22
test.ar
22
test.ar
@@ -1,15 +1,9 @@
|
|||||||
let maths = map()
|
a = array()
|
||||||
|
i = 0
|
||||||
|
|
||||||
maths.ln(x) = do
|
forever do
|
||||||
let n = 1e10
|
a = append(a, i)
|
||||||
return n * ((x^(1/n)) - 1)
|
i = i + 1
|
||||||
|
if (i % 1000000 == 0) do
|
||||||
let __ln10cache = ln(10)
|
term.log(i)
|
||||||
|
break
|
||||||
maths.log(x) = do
|
|
||||||
return ln(x) / __ln10cache
|
|
||||||
|
|
||||||
maths.logN(n,x) = do
|
|
||||||
return ln(x) / ln(n)
|
|
||||||
|
|
||||||
term.log(maths.log(10000), array(maths))
|
|
||||||
Reference in New Issue
Block a user