diff --git a/src/call.go b/src/call.go index 880984d..84311b7 100644 --- a/src/call.go +++ b/src/call.go @@ -32,36 +32,26 @@ func parseCall(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, trim := strings.TrimSpace(code.code) trim = trim[:len(trim)-1] splitby := strings.Split(trim, "(") - - var works bool - var callable any - var arguments []any 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, false) - arguments = args if !success { if i == len(splitby)-1 { return nil, false, argserr, 1 } continue } - resp, worked, _, _ := translateVal(UNPARSEcode{code: name, realcode: code.realcode, line: index + 1, path: code.path}, index, codelines, 0) + resp, worked, err, linecount := translateVal(UNPARSEcode{code: name, realcode: code.realcode, line: index + 1, path: code.path}, index, codelines, 0) if !worked { if i == len(splitby)-1 { - return nil, false, ArErr{"Syntax Error", "invalid callable", code.line, code.path, code.realcode, true}, 1 + return nil, false, err, 1 } continue } - works = true - callable = resp - break + return call{Callable: resp, Args: args, Line: code.line, Code: code.realcode, Path: code.path}, true, ArErr{}, linecount } - if !works { - return nil, false, ArErr{"Syntax Error", "invalid call", code.line, code.path, code.realcode, true}, 1 - } - return call{Callable: callable, Args: arguments, Line: code.line, Code: code.realcode, Path: code.path}, true, ArErr{}, 1 + return nil, false, ArErr{"Syntax Error", "invalid call", code.line, code.path, code.realcode, true}, 1 } func runCall(c call, stack stack, stacklevel int) (any, ArErr) { @@ -129,7 +119,7 @@ func runCall(c call, stack stack, stacklevel int) (any, ArErr) { l[param] = args[i] } resp, err := runVal(x.run, append(x.stack, Map(l)), stacklevel+1) - return ThrowOnNonLoop(openReturn(resp), err) + return openReturn(resp), err } return nil, ArErr{"Runtime Error", "type '" + typeof(callable) + "' is not callable", c.Line, c.Path, c.Code, true} } @@ -151,7 +141,7 @@ func builtinCall(callable any, args []any) (any, ArErr) { level.obj[param] = args[i] } resp, err := runVal(x.run, append(x.stack, level), 0) - return ThrowOnNonLoop(openReturn(resp), err) + return openReturn(resp), err } return nil, ArErr{TYPE: "Runtime Error", message: "type '" + typeof(callable) + "' is not callable", EXISTS: true} } diff --git a/src/comment.go b/src/comment.go index ef44e89..8c85a78 100644 --- a/src/comment.go +++ b/src/comment.go @@ -24,7 +24,7 @@ func parseComment(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bo if isBlank(UNPARSEcode{code: joined, realcode: code.realcode, line: code.line, path: code.path}) { return nil, true, ArErr{}, step } - resp, worked, _, s := translateVal(UNPARSEcode{code: joined, realcode: code.realcode, line: code.line, path: code.path}, index, codelines, 2) + resp, worked, _, s := translateVal(UNPARSEcode{code: joined, realcode: code.realcode, line: code.line, path: code.path}, index, codelines, 3) step += s - 1 if worked { return resp, true, ArErr{}, step diff --git a/src/dowraps.go b/src/dowraps.go index be8f996..9747925 100644 --- a/src/dowraps.go +++ b/src/dowraps.go @@ -38,7 +38,7 @@ func parseDoWrap(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, boo return nil, false, ArErr{"Syntax Error", "invalid indent", i, code.path, codelines[i].code, true}, 1 } - val, _, err, step := translateVal(codelines[i], i, codelines, 2) + val, _, err, step := translateVal(codelines[i], i, codelines, 3) i += step if err.EXISTS { return nil, false, err, i - index diff --git a/src/ifstatement.go b/src/ifstatement.go index 960da3a..9727517 100644 --- a/src/ifstatement.go +++ b/src/ifstatement.go @@ -69,7 +69,7 @@ func parseIfStatement(code UNPARSEcode, index int, codeline []UNPARSEcode) (ifst }, i, codeline, - 2, + 1, ) if err.EXISTS || !worked { return ifstatement{}, worked, err, step diff --git a/src/import.go b/src/import.go index 2c79f03..0efb2b6 100644 --- a/src/import.go +++ b/src/import.go @@ -114,7 +114,7 @@ func importMod(realpath string, origin string, main bool, global ArObject) (ArOb localvars := Map(anymap{ "program": Map(anymap{ "args": ArArray(ArgsArArray), - "origin": origin, + "origin": ArString(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} @@ -124,16 +124,16 @@ func importMod(realpath string, origin string, main bool, global ArObject) (ArOb } return importMod(args[0].(string), filepath.Dir(filepath.ToSlash(p)), false, global) }}, - "cwd": ex, - "exc": exc, + "cwd": ArString(ex), + "exc": ArString(exc), "file": Map(anymap{ - "name": filepath.Base(p), - "path": p, + "name": ArString(filepath.Base(p)), + "path": ArString(p), }), "main": main, }), }) - _, runimeErr := ThrowOnNonLoop(run(translated, stack{global, localvars, local})) + _, runimeErr := run(translated, stack{global, localvars, local}) importing[p] = false if runimeErr.EXISTS { return ArObject{}, runimeErr diff --git a/src/jumpStatements.go b/src/jumpStatements.go index f151655..8f99f5f 100644 --- a/src/jumpStatements.go +++ b/src/jumpStatements.go @@ -71,6 +71,7 @@ func runReturn(code CallReturn, stack stack, stacklevel int) (any, ArErr) { if err.EXISTS { return nil, err } + v = openReturn(v) val = v } return Return{ @@ -81,6 +82,19 @@ func runReturn(code CallReturn, stack stack, stacklevel int) (any, ArErr) { }, ArErr{} } +func translateThrowOnNonLoop(val any) ArErr { + switch x := val.(type) { + case Break: + return ArErr{"Break Error", "break can only be used in loops", x.line, x.path, x.code, true} + case Continue: + return ArErr{"Continue Error", "continue can only be used in loops", x.line, x.path, x.code, true} + case CallReturn: + return ArErr{"Return Error", "return can only be used in do wraps", x.line, x.path, x.code, true} + default: + return ArErr{} + } +} + func openReturn(resp any) any { switch x := resp.(type) { case Return: diff --git a/src/shell.go b/src/shell.go index 7ce72a9..e1f3c0a 100644 --- a/src/shell.go +++ b/src/shell.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "os/signal" + "strings" ) func shell(global ArObject) { @@ -18,23 +19,26 @@ func shell(global ArObject) { } } }() + fmt.Print("\x1b[32;5;240mWelcome to the Argon v3!\x1b[0m\n\n") for { - indo := false + indent := 0 + previous := 0 totranslate := []UNPARSEcode{} - code := input("\x1b[38;5;240m>>> \x1b[0m\x1b[1;5;240m") - fmt.Print("\x1b[0m") - if code == "" { - continue - } - indo = true - totranslate = append(totranslate, UNPARSEcode{code, code, 1, ""}) - for i := 2; indo; i++ { - code := input("\x1b[38;5;240m... \x1b[0m\x1b[1;5;240m") + textBefore := ">>>" + for i := 1; indent > 0 || (previous != indent && indent >= 0) || i == 1; i++ { + indentStr := strings.Repeat(" ", indent) + code := indentStr + input("\x1b[38;5;240m"+textBefore+indentStr+" \x1b[0m\x1b[1;5;240m") fmt.Print("\x1b[0m") totranslate = append(totranslate, UNPARSEcode{code, code, i, ""}) - if code == "" { - indo = false + trimmed := strings.TrimSpace(code) + split := strings.Split(trimmed, " ") + previous = indent + if split[len(split)-1] == "do" { + indent++ + } else if trimmed == "" { + indent-- } + textBefore = "..." } translated, translationerr := translate(totranslate) count := len(translated) @@ -47,7 +51,6 @@ func shell(global ArObject) { if runimeErr.EXISTS { panicErr(runimeErr) } else if count == 1 { - fmt.Println(anyToArgon(output, true, true, 3, 0, true, 1)) } } diff --git a/src/translate.go b/src/translate.go index d608ff3..b2b9c74 100644 --- a/src/translate.go +++ b/src/translate.go @@ -30,36 +30,12 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i err ArErr = ArErr{"Syntax Error", "invalid syntax", code.line, code.path, code.realcode, true} i int = 1 ) - if isLine == 2 { - if isDeleteVariable(code) { - resp, worked, err, i = parseDelete(code, index, codelines) - if !worked { - knownFailures[code.code] = err - } - return resp, worked, err, i - } else if isComment(code) { + if isLine == 3 { + if isComment(code) { resp, worked, err, i = parseComment(code, index, codelines) if worked { return resp, worked, err, i } - } else if isReturn(code) { - resp, worked, err, i = parseReturn(code, index, codelines) - if !worked { - knownFailures[code.code] = err - } - return resp, worked, err, i - } else if isBreak(code) { - resp, worked, err, i = parseBreak(code) - if !worked { - knownFailures[code.code] = err - } - return resp, worked, err, i - } else if isContinue(code) { - resp, worked, err, i = parseContinue(code) - if !worked { - knownFailures[code.code] = err - } - return resp, worked, err, i } else if isIfStatement(code) { resp, worked, err, i = parseIfStatement(code, index, codelines) if !worked { @@ -99,6 +75,34 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i } } + if isLine >= 2 { + if isReturn(code) { + resp, worked, err, i = parseReturn(code, index, codelines) + if !worked { + knownFailures[code.code] = err + } + return resp, worked, err, i + } else if isBreak(code) { + resp, worked, err, i = parseBreak(code) + if !worked { + knownFailures[code.code] = err + } + return resp, worked, err, i + } else if isContinue(code) { + resp, worked, err, i = parseContinue(code) + if !worked { + knownFailures[code.code] = err + } + return resp, worked, err, i + } else if isDeleteVariable(code) { + resp, worked, err, i = parseDelete(code, index, codelines) + if !worked { + knownFailures[code.code] = err + } + return resp, worked, err, i + } + } + if isLine >= 1 { if isDoWrap(code) { resp, worked, err, i = parseDoWrap(code, index, codelines) @@ -109,7 +113,7 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i } } - if isLine == 2 { + if isLine > 1 { isLine = 1 } @@ -233,15 +237,15 @@ func translate(codelines []UNPARSEcode) ([]any, ArErr) { if currentindent != 0 { return nil, ArErr{"Syntax Error", "invalid indent", codelines[i].line, codelines[i].path, codelines[i].realcode, true} } - val, _, err, step := translateVal(codelines[i], i, codelines, 2) - switch val.(type) { - case CallReturn: - return nil, ArErr{"Runtime Error", "Jump statment at top level", codelines[i].line, codelines[i].path, codelines[i].realcode, true} - } + val, _, err, step := translateVal(codelines[i], i, codelines, 3) i += step if err.EXISTS { return nil, err } + err = translateThrowOnNonLoop(val) + if err.EXISTS { + return nil, err + } translated = append(translated, val) } diff --git a/tests/oop.ar b/tests/oop.ar index 57a080a..0525fb6 100644 --- a/tests/oop.ar +++ b/tests/oop.ar @@ -1,4 +1,4 @@ -let toyTank(colour , name) = do +let toyTank(colour, name) = do let class = {} class.getColour() = do term.log("My colour is", colour) diff --git a/tests/stack test.ar b/tests/stack test.ar index 4bcaceb..21341e7 100644 --- a/tests/stack test.ar +++ b/tests/stack test.ar @@ -4,4 +4,14 @@ do let x = 20 term.log(x) +term.log(x) + +term.log() + +let x = 10 + +do + x = 20 + term.log(x) + term.log(x) \ No newline at end of file diff --git a/tests/testing.ar b/tests/testing.ar new file mode 100644 index 0000000..e69de29