diff --git a/.gitignore b/.gitignore index 9f8352f..a32fba6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ main.spec dist-*/ build/ assets/ -run-miled.spec \ No newline at end of file +run-miled.spec +pyinstaller-build \ No newline at end of file diff --git a/interpreter/builtins.py b/interpreter/builtins.py index 5de9caf..c423915 100644 --- a/interpreter/builtins.py +++ b/interpreter/builtins.py @@ -120,6 +120,8 @@ def map_over(f: Caller, old_list: list, table: Env): "wS": Caller(1, lambda x, _: (x[0][1].split(), None)), ",S": Caller(1, lambda x, _: (x[0][1].split(","), None)), + "join": Caller(2, lambda x, _: (x[0][1].join(x[1][1]), None)), + "map": Caller(2, lambda x, t: (map_over(x[0][1], x[1][1], t), None)), # * ARITHMETIC FUNCTIONS diff --git a/interpreter/lex.py b/interpreter/lex.py index 9bf8f90..a451348 100644 --- a/interpreter/lex.py +++ b/interpreter/lex.py @@ -33,7 +33,12 @@ def to_token(buf: str) -> Token: if buf[0] == "\"" and buf[-1] == "\"": return Token( Token.VAL, - buf[1:-1].replace("\\\"", "\"").replace("\\\\", "\\") + buf[1:-1] + .replace(r"\"", "\"") + .replace(r"\\", "\\") + .replace(r"\n", "\n") + .replace(r"\t", "\t") + .replace(r"\r", "\r") ) elif is_int(buf): return Token(Token.VAL, int(buf)) @@ -45,6 +50,8 @@ def to_token(buf: str) -> Token: return Token(Token.VAL, False) elif buf == "??": return Token(Token.VAL, None) + elif buf == "[]": + return Token(Token.VAL, []) elif buf in KEYWORDS: return Token(Token.KW, buf) else: diff --git a/interpreter/readable_test.py b/interpreter/readable_test.py index 6599014..24790e1 100644 --- a/interpreter/readable_test.py +++ b/interpreter/readable_test.py @@ -110,18 +110,18 @@ def test_interpreter(self): ) self.assertEqual( # A FizzBuzz Example - " ".join([ + "\n".join([ "FizzBuzz" if i % 3 == 0 and i % 5 == 0 else "Fizz" if i % 3 == 0 else "Buzz" if i % 5 == 0 else str(i) for i in range(1, 101) - ]) + " ", - Interpreter(""" + ]), + Interpreter(r""" := x 0 - := s "" + := s [] while: ~ += x 1 != x 101 ; - += s if:: + push s if:: & div 3 x div 5 x "FizzBuzz" else if:: div 3 x "Fizz" @@ -131,9 +131,8 @@ def test_interpreter(self): :fi :fi :fi - += s " " :ihw - s + join "\n" s """).run() ) self.assertEqual( diff --git a/main.py b/main.py index 570fbeb..19bd14b 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,18 @@ from interpreter.interpret import Interpreter from argparse import ArgumentParser + +def try_run(code: str): + itpr = Interpreter(code) + try: + print(itpr.run()) + except Exception as IE: + print("Cannot run program, an error occurred:") + print(IE) + print("near: \"" + str(itpr.tokens[itpr.i].value) + "\" at word #" + str(itpr.i)) + print("Check your code. If you confirm there shouldn't be any problem, report an issue.") + + if __name__ == "__main__": parser = ArgumentParser("Miled language interpreter") parser.add_argument("-f", "--file") @@ -10,19 +22,11 @@ try: if args.file is not None: file = open(args.file, "r").read() - print(Interpreter(file).run()) + try_run(file) elif args.code is not None: - print(Interpreter(args.code).run()) + try_run(args.code) except FileNotFoundError: print("File not found.") - except IndexError as E: - print(E) - print("An IndexError occurred. It's likely that you've used an index out of range, or you have too many " - "enclosing marks. Check your code.") - except TypeError as E: - print(E) - print("A TypeError occurred. It's likely that you've forgot to enclose a Caller, or you messed " - "up the types. Use \"->...\" commands to convert types.") except Exception as E: - print("An error occurred.") + print("Unknown error occurred:") print(E)