2025-10-13 06:55:35 +11:00
|
|
|
from lexer import Lexer
|
2025-10-13 17:41:07 +11:00
|
|
|
from plasma_parser import Parser
|
2025-10-13 21:05:03 +11:00
|
|
|
from compiler import Compiler
|
2025-10-13 17:41:07 +11:00
|
|
|
from AST import Program
|
|
|
|
|
import json
|
2025-10-14 19:22:59 +11:00
|
|
|
import time
|
2025-10-18 07:40:47 +11:00
|
|
|
import sys
|
|
|
|
|
from argparse import ArgumentParser, Namespace
|
2025-10-13 06:55:35 +11:00
|
|
|
|
2025-10-13 21:05:03 +11:00
|
|
|
from llvmlite import ir
|
2025-10-14 19:22:59 +11:00
|
|
|
import llvmlite.binding as llvm
|
2025-10-13 21:05:03 +11:00
|
|
|
from ctypes import CFUNCTYPE, c_int, c_float
|
|
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
|
|
|
|
|
def parse_arguments() -> Namespace:
|
|
|
|
|
arg_parser: ArgumentParser = ArgumentParser(
|
|
|
|
|
"Plasma",
|
|
|
|
|
description="The compiler for the Plasma programming language."
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
arg_parser.add_argument("file_path", type=str, help="path to the entry point of your plasma program (ex. \"main.pla\")")
|
|
|
|
|
arg_parser.add_argument("--tokens", action="store_true", help="display the tokenized code")
|
|
|
|
|
arg_parser.add_argument("--ast", default=None, help="export the generated AST to a JSON file")
|
|
|
|
|
arg_parser.add_argument("--llvm", default=None, help="export the generated LLVM IR to a file")
|
|
|
|
|
arg_parser.add_argument("--silent", action="store_true", help="don't print anything!!!!")
|
|
|
|
|
|
|
|
|
|
return arg_parser.parse_args()
|
2025-10-13 06:55:35 +11:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2025-10-18 07:40:47 +11:00
|
|
|
args = parse_arguments()
|
|
|
|
|
if args.silent:
|
|
|
|
|
sys.stdout = None
|
|
|
|
|
|
|
|
|
|
with open(args.file_path) as f:
|
2025-10-13 06:55:35 +11:00
|
|
|
code: str = f.read()
|
|
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
if args.tokens:
|
2025-10-13 06:55:35 +11:00
|
|
|
debug_lex: Lexer = Lexer(source=code)
|
|
|
|
|
while debug_lex.current_char is not None:
|
2025-10-13 17:41:07 +11:00
|
|
|
print(debug_lex.next_token())
|
|
|
|
|
|
|
|
|
|
l: Lexer = Lexer(source=code)
|
|
|
|
|
p: Parser = Parser(lexer=l)
|
|
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
parse_st: float = time.time()
|
2025-10-13 21:05:03 +11:00
|
|
|
program: Program = p.parse_program()
|
2025-10-18 07:40:47 +11:00
|
|
|
parse_et: float = time.time()
|
2025-10-18 19:28:54 +11:00
|
|
|
#print(f"Parsed in {round((parse_et - parse_st) * 1000, 6)} ms.")
|
2025-10-18 07:40:47 +11:00
|
|
|
|
2025-10-13 21:05:03 +11:00
|
|
|
if len(p.errors) > 0:
|
|
|
|
|
for err in p.errors:
|
|
|
|
|
print(err)
|
|
|
|
|
exit(1)
|
|
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
if args.ast:
|
2025-10-13 17:41:07 +11:00
|
|
|
print("===== PARSER DEBUG =====")
|
2025-10-13 21:05:03 +11:00
|
|
|
#program: Program = p.parse_program()
|
2025-10-13 17:41:07 +11:00
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
with open(args.ast, "w") as f:
|
2025-10-13 17:41:07 +11:00
|
|
|
json.dump(program.json(), f, indent=4)
|
|
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
print(f"Wrote AST to \"{args.ast}\" successfully.")
|
2025-10-13 21:05:03 +11:00
|
|
|
|
|
|
|
|
c: Compiler = Compiler()
|
2025-10-18 07:40:47 +11:00
|
|
|
|
|
|
|
|
compiler_st: float = time.time()
|
2025-10-13 21:05:03 +11:00
|
|
|
c.compile(program)
|
2025-10-18 07:40:47 +11:00
|
|
|
compiler_et: float = time.time()
|
2025-10-18 19:28:54 +11:00
|
|
|
#print(f"Compiled in {round((compiler_et - compiler_st) * 1000, 6)} ms.")
|
2025-10-13 21:05:03 +11:00
|
|
|
|
|
|
|
|
module: ir.Module = c.module
|
2025-10-14 19:22:59 +11:00
|
|
|
module.triple = llvm.get_default_triple()
|
2025-10-13 21:05:03 +11:00
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
if args.llvm:
|
|
|
|
|
with open(args.llvm, "w") as f:
|
2025-10-14 19:22:59 +11:00
|
|
|
f.write(str(module))
|
|
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
llvm.initialize_native_target()
|
|
|
|
|
llvm.initialize_native_asmparser()
|
|
|
|
|
llvm.initialize_native_asmprinter()
|
2025-10-14 19:22:59 +11:00
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
try:
|
|
|
|
|
llvm_ir_parsed = llvm.parse_assembly(str(module))
|
|
|
|
|
llvm_ir_parsed.verify()
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(e)
|
|
|
|
|
raise
|
2025-10-14 19:22:59 +11:00
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
target_machine = llvm.Target.from_default_triple().create_target_machine()
|
2025-10-14 19:22:59 +11:00
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
engine = llvm.create_mcjit_compiler(llvm_ir_parsed, target_machine)
|
|
|
|
|
engine.finalize_object()
|
2025-10-14 19:22:59 +11:00
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
entry = engine.get_function_address("main")
|
|
|
|
|
cfunc = CFUNCTYPE(c_int)(entry)
|
2025-10-14 19:22:59 +11:00
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
st = time.time()
|
2025-10-14 19:22:59 +11:00
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
result = cfunc()
|
2025-10-14 19:22:59 +11:00
|
|
|
|
2025-10-18 07:40:47 +11:00
|
|
|
et = time.time()
|
2025-10-14 19:22:59 +11:00
|
|
|
|
2025-10-18 19:28:54 +11:00
|
|
|
#print(f"\n\nProgram returned: {result}\n=== Executed in {round((et - st) * 1000, 6)} ms. ===")
|
|
|
|
|
exit(result)
|