mirror of
https://github.com/Open-Argon/argon-v3.git
synced 2025-12-06 08:56:07 +00:00
add for loop
This commit is contained in:
@@ -1,16 +1,14 @@
|
||||
let read(path) = do
|
||||
file = open(path, "r")
|
||||
text = file.text()
|
||||
f = file.read(path)
|
||||
text = f.text()
|
||||
data = []
|
||||
splitlines = text.split("\n")
|
||||
i = 0
|
||||
while (i < splitlines.length) do
|
||||
for (i from 0 to splitlines.length) do
|
||||
values = []
|
||||
in_quotes = false
|
||||
start = 0
|
||||
line = splitlines[i]
|
||||
j = 0
|
||||
while (j < line.length) do
|
||||
for (j from 0 to line.length) do
|
||||
char = line[j]
|
||||
if (char == "," && not in_quotes) do
|
||||
value = line[start:j].rightstrip("\r").strip()
|
||||
@@ -27,8 +25,6 @@ let read(path) = do
|
||||
value = value[1:value.length - 1]
|
||||
value = value.replace("\"\"", "\"")
|
||||
values.append(value)
|
||||
j = j + 1
|
||||
data.append(values)
|
||||
i = i + 1
|
||||
|
||||
return data
|
||||
@@ -130,7 +130,7 @@ func init() {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot ceil '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars.obj["sqrt"] = builtinFunc{"sqrt", ArgonSqrt}
|
||||
vars.obj["open"] = builtinFunc{"open", ArOpen}
|
||||
vars.obj["file"] = ArFile
|
||||
vars.obj["random"] = ArRandom
|
||||
vars.obj["json"] = ArJSON
|
||||
vars.obj["sin"] = ArSin
|
||||
|
||||
75
src/file.go
75
src/file.go
@@ -7,26 +7,29 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func ArOpen(args ...any) (any, ArErr) {
|
||||
if len(args) > 2 {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "open takes 1 or 2 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
var ArFile = Map(anymap{
|
||||
"read": builtinFunc{"read", ArRead},
|
||||
"write": builtinFunc{"write", ArWrite},
|
||||
})
|
||||
|
||||
func readtext(file *os.File) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
_, err := io.Copy(&buf, file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func ArRead(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "read takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "string" {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "open 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}
|
||||
}
|
||||
path := args[0].(string)
|
||||
mode := "r"
|
||||
if len(args) == 2 {
|
||||
if typeof(args[1]) != "string" {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "open takes a string not type '" + typeof(args[1]) + "'", EXISTS: true}
|
||||
}
|
||||
mode = args[1].(string)
|
||||
}
|
||||
if mode != "r" && mode != "w" {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "open mode must be 'r', or 'w'", EXISTS: true}
|
||||
}
|
||||
if mode == "r" {
|
||||
file, err := os.Open(path)
|
||||
filename := args[0].(string)
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
@@ -36,20 +39,27 @@ func ArOpen(args ...any) (any, ArErr) {
|
||||
if err != nil {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return ArString(text), ArErr{}
|
||||
},
|
||||
},
|
||||
return text, ArErr{}
|
||||
}},
|
||||
"json": builtinFunc{"json", func(...any) (any, ArErr) {
|
||||
text, err := readtext(file)
|
||||
if err != nil {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return jsonparse(text), ArErr{}
|
||||
},
|
||||
},
|
||||
}},
|
||||
}), ArErr{}
|
||||
}
|
||||
file, err := os.Create(path)
|
||||
|
||||
func ArWrite(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "write takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "string" {
|
||||
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 ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
@@ -75,25 +85,6 @@ func ArOpen(args ...any) (any, ArErr) {
|
||||
file.Write([]byte(jsonstr))
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
"append": builtinFunc{"append", func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "append takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "string" {
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "append takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
}
|
||||
file.Write([]byte(args[0].(string)))
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
}), ArErr{}
|
||||
|
||||
}
|
||||
|
||||
func readtext(file *os.File) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
_, err := io.Copy(&buf, file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
120
src/forloop.go
Normal file
120
src/forloop.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var forloopCompile = makeRegex(`( *)for( +)\(( *)` + spacelessVariable + `( +)from( +)(\n|.)+to( +)(\n|.)+(( +)step( +)(\n|.)+)?( *)\)( *)(\n|.)+`)
|
||||
|
||||
type forLoop struct {
|
||||
variable string
|
||||
from any
|
||||
to any
|
||||
step any
|
||||
body any
|
||||
line int
|
||||
code string
|
||||
path string
|
||||
}
|
||||
|
||||
func isForLoop(code UNPARSEcode) bool {
|
||||
return forloopCompile.MatchString(code.code)
|
||||
}
|
||||
|
||||
func parseForLoop(code UNPARSEcode, index int, codelines []UNPARSEcode) (forLoop, bool, ArErr, int) {
|
||||
totalstep := 0
|
||||
trimmed := strings.TrimSpace(strings.TrimSpace(code.code)[3:])[1:]
|
||||
split := strings.SplitN(trimmed, " from ", 2)
|
||||
name := strings.TrimSpace(split[0])
|
||||
split = strings.SplitN(split[1], " to ", 2)
|
||||
from := strings.TrimSpace(split[0])
|
||||
fromval, worked, err, fromstep := translateVal(UNPARSEcode{code: from, realcode: code.realcode, line: index + 1, path: code.path}, index, codelines, 0)
|
||||
if !worked {
|
||||
return forLoop{}, worked, err, fromstep
|
||||
}
|
||||
totalstep += fromstep
|
||||
tosplit := strings.Split(split[1], ")")
|
||||
for i := len(tosplit) - 1; i >= 0; i-- {
|
||||
innertotalstep := 0
|
||||
val := strings.Join(tosplit[:i], ")")
|
||||
valsplit := strings.SplitN(val, " step ", 2)
|
||||
var stepval any
|
||||
if len(valsplit) == 2 {
|
||||
step := strings.TrimSpace(valsplit[1])
|
||||
stepval_, worked, err, stepstep := translateVal(UNPARSEcode{code: step, realcode: code.realcode, line: code.line, path: code.path}, index, codelines, 0)
|
||||
if !worked {
|
||||
if i == 0 {
|
||||
return forLoop{}, worked, err, stepstep
|
||||
}
|
||||
continue
|
||||
}
|
||||
innertotalstep += stepstep - 1
|
||||
stepval = stepval_
|
||||
} else {
|
||||
stepval = newNumber().SetInt64(1)
|
||||
}
|
||||
to := strings.TrimSpace(valsplit[0])
|
||||
toval, worked, err, tostep := translateVal(UNPARSEcode{code: to, realcode: code.realcode, line: code.line, path: code.path}, index, codelines, 0)
|
||||
if !worked {
|
||||
if i == 0 {
|
||||
return forLoop{}, worked, err, tostep
|
||||
}
|
||||
continue
|
||||
}
|
||||
innertotalstep += tostep - 1
|
||||
body := strings.Join(tosplit[i:], ")")
|
||||
bodyval, worked, err, bodystep := translateVal(UNPARSEcode{code: body, realcode: code.realcode, line: code.line, path: code.path}, index, codelines, 1)
|
||||
if !worked {
|
||||
if i == 0 {
|
||||
return forLoop{}, worked, err, bodystep
|
||||
}
|
||||
continue
|
||||
}
|
||||
innertotalstep += bodystep - 1
|
||||
return forLoop{variable: name, from: fromval, to: toval, step: stepval, body: bodyval, line: code.line, code: code.code, path: code.path}, true, ArErr{}, totalstep + innertotalstep
|
||||
}
|
||||
return forLoop{}, false, ArErr{"Syntax Error", "invalid for loop", code.line, code.path, code.realcode, true}, 1
|
||||
}
|
||||
func runForLoop(loop forLoop, stack stack, stacklevel int) (any, ArErr) {
|
||||
fromval, err := runVal(loop.from, stack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
}
|
||||
if typeof(fromval) != "number" {
|
||||
return nil, ArErr{"Type Error", "for loop from value must be a number", loop.line, loop.path, loop.code, true}
|
||||
}
|
||||
from := fromval.(number)
|
||||
toval, err := runVal(loop.to, stack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
}
|
||||
if typeof(toval) != "number" {
|
||||
return nil, ArErr{"Type Error", "for loop to value must be a number", loop.line, loop.path, loop.code, true}
|
||||
}
|
||||
to := toval.(number)
|
||||
stepval, err := runVal(loop.step, stack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
}
|
||||
if typeof(stepval) != "number" {
|
||||
return nil, ArErr{"Type Error", "for loop step value must be a number", loop.line, loop.path, loop.code, true}
|
||||
}
|
||||
step := stepval.(number)
|
||||
for i := newNumber().Set(from); i.Cmp(to) == -1; i = i.Add(i, step) {
|
||||
resp, err := runVal(loop.body, append(stack, Map(anymap{
|
||||
loop.variable: newNumber().Set(i),
|
||||
})), stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
}
|
||||
switch x := resp.(type) {
|
||||
case Return:
|
||||
return x, ArErr{}
|
||||
case Break:
|
||||
return nil, ArErr{}
|
||||
case Continue:
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil, ArErr{}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ func importMod(realpath string, origin string, main bool) (ArObject, ArErr) {
|
||||
"scope": global,
|
||||
}),
|
||||
})
|
||||
_, runimeErr, _ := run(translated, stack{vars, localvars, global})
|
||||
_, runimeErr := ThrowOnNonLoop(run(translated, stack{vars, localvars, global}))
|
||||
importing[p] = false
|
||||
if runimeErr.EXISTS {
|
||||
return ArObject{}, runimeErr
|
||||
|
||||
14
src/run.go
14
src/run.go
@@ -159,6 +159,14 @@ func runVal(line any, stack stack, stacklevel int) (any, ArErr) {
|
||||
break
|
||||
}
|
||||
return runWhileLoop(x, stack, stacklevel+1)
|
||||
case forLoop:
|
||||
if stackoverflow {
|
||||
linenum = x.line
|
||||
path = x.path
|
||||
code = x.code
|
||||
break
|
||||
}
|
||||
return runForLoop(x, stack, stacklevel+1)
|
||||
case CreateArray:
|
||||
if stackoverflow {
|
||||
linenum = x.line
|
||||
@@ -203,14 +211,14 @@ func runVal(line any, stack stack, stacklevel int) (any, ArErr) {
|
||||
}
|
||||
|
||||
// returns error
|
||||
func run(translated []any, stack stack) (any, ArErr, any) {
|
||||
func run(translated []any, stack stack) (any, ArErr) {
|
||||
var output any = nil
|
||||
for _, val := range translated {
|
||||
val, err := runVal(val, stack, 0)
|
||||
output = val
|
||||
if err.EXISTS {
|
||||
return nil, err, output
|
||||
return output, err
|
||||
}
|
||||
}
|
||||
return nil, ArErr{}, output
|
||||
return output, ArErr{}
|
||||
}
|
||||
|
||||
@@ -41,10 +41,13 @@ func shell() {
|
||||
if translationerr.EXISTS {
|
||||
panicErr(translationerr)
|
||||
}
|
||||
_, runimeErr, output := run(translated, global)
|
||||
output, runimeErr := ThrowOnNonLoop(run(translated, global))
|
||||
output = openReturn(output)
|
||||
|
||||
if runimeErr.EXISTS {
|
||||
panicErr(runimeErr)
|
||||
} else if count == 1 {
|
||||
|
||||
fmt.Println(anyToArgon(output, true, true, 3, 0, true, 1))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,8 +187,11 @@ func ArString(str string) ArObject {
|
||||
if len(a) != 1 {
|
||||
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
|
||||
}
|
||||
if typeof(a[0]) != "array" {
|
||||
return nil, ArErr{"TypeError", "expected array, got " + typeof(a[0]), 0, "", "", true}
|
||||
}
|
||||
output := []string{str}
|
||||
for _, v := range a {
|
||||
for _, v := range a[0].([]any) {
|
||||
if typeof(v) != "string" {
|
||||
return nil, ArErr{"TypeError", "expected string, got " + typeof(v), 0, "", "", true}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i
|
||||
return parseWhileLoop(code, index, codelines)
|
||||
} else if isForeverLoop(code) {
|
||||
return parseForeverLoop(code, index, codelines)
|
||||
} else if isForLoop(code) {
|
||||
return parseForLoop(code, index, codelines)
|
||||
} else if isGenericImport(code) {
|
||||
return parseGenericImport(code, index, codelines)
|
||||
}
|
||||
|
||||
@@ -108,15 +108,17 @@ func parseForeverLoop(code UNPARSEcode, index int, codeline []UNPARSEcode) (whil
|
||||
}
|
||||
|
||||
func runWhileLoop(loop whileLoop, stack stack, stacklevel int) (any, ArErr) {
|
||||
newstack := append(stack, newscope())
|
||||
for {
|
||||
condition, err := runVal(loop.condition, stack, stacklevel+1)
|
||||
condition, err := runVal(loop.condition, newstack, stacklevel+1)
|
||||
newbodystack := append(newstack, newscope())
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
}
|
||||
if !anyToBool(condition) {
|
||||
break
|
||||
}
|
||||
resp, err := runVal(loop.body, stack, stacklevel+1)
|
||||
resp, err := runVal(loop.body, newbodystack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user