This repository has been archived by the owner on Jul 7, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
compiler.py
139 lines (111 loc) · 3.97 KB
/
compiler.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import time
BEGIN = time.time()
import logger
import lexer
import syntax
import semantics
import codegen
import optimization
import argparse
from colorama import init
from colorama import Fore, Back, Style
import sys
import os
import subprocess
def Run(fileName, DEBUG, TEST, platform):
file = open(fileName, "r")
raw = file.read()
#TODO(Noah): What happens if the file read fails?
file.close()
tokens = lexer.Run(raw)
if DEBUG:
for token in tokens.tokens:
logger.Log("TYPE: " + token.type + ", VALUE: " + token.value)
tree = syntax.Run(tokens, logger)
if not tree:
sys.exit()
if DEBUG:
tree.Print(0)
#tree.PrintWeights(0)
#print("Depth: " + str(tree.depth))
#annotatedTree, result = semantics.Run(tree, logger)
#if result == False:
# sys.exit()
file = open(fileName + ".asm", "w")
codegen.Run(platform, tree, file)
file.close()
#instructions = optimization.Run(instructions)
#TODO(Noah): There is more room for error here
#write out assembler instructions
# Assemble and link the code (using 3rd party software)
exe_name = "{}.exe".format(fileName)
if (platform == "WINDOWS"):
subprocess.run(["nasm", "-fwin32", "{}.asm".format(fileName)])
subprocess.run(["link", "/subsystem:console", "/entry:start" ,
"{}.obj".format(fileName), "/OUT:{}".format(exe_name)])
elif (platform == "LINUX"):
pass
return_val = 0
if TEST:
if os.path.isfile(exe_name):
if DEBUG:
print("Running {}".format(exe_name))
result = subprocess.run([exe_name])
return_val = result.returncode
if DEBUG:
print("Return Code: {}".format(result.returncode))
END = time.time()
ELAPSED = round((END - BEGIN) * 1000, 3)
logger.Log("Elapsed: " + str(ELAPSED) + "ms")
return return_val
def colored(string, color):
if color == "green":
return Fore.GREEN + string
elif color == "red":
return Fore.RED + string
def SingleTest(fileName, desired_result):
global PLATFORM
debug = False
test = True
result = Run(fileName, debug, test, PLATFORM)
if desired_result == result:
print(colored("{} works.".format(fileName), "green"))
print(Style.RESET_ALL)
else:
print(colored("Error: {} does not work.".format(fileName), "red"))
print(Style.RESET_ALL)
def RunAllTests():
global PLATFORM
init()
PLATFORM = "WINDOWS"
SingleTest("tests/variable_scoping.c", 3)
SingleTest("tests/variables.c", 5)
SingleTest("tests/expression.c", 1)
SingleTest("tests/comments.c", 0)
SingleTest("tests/function.c", 65)
SingleTest("tests/function2.c", 128)
SingleTest("tests/factorial.c", 6)
SingleTest("tests/if.c", 100)
SingleTest("tests/if2.c", 80)
SingleTest("tests/if3.c", 40)
SingleTest("tests/conditional.c", 12)
SingleTest("tests/fib.c", 13)
SingleTest("tests/for.c", 5)
SingleTest("tests/while.c", 10)
if __name__ == "__main__":
parser = argparse.ArgumentParser(prog='Plasma Compiler',
description='Compile C programs.')
parser.add_argument('filename', nargs='?', help="The file to process.", default=None)
parser.add_argument('-d', '--debug', action='store_true', help="Enable debug mode.")
parser.add_argument('-r', '--run', action='store_true', help="Run code after compile.")
parser.add_argument('-t', '--test', action='store_true', help="Run all tests (ignores positional argument).")
args = parser.parse_args()
if args.test:
RunAllTests()
else:
if args.filename is not None:
platform = "WINDOWS"
DEBUG = args.debug
Run(args.filename, DEBUG, args.run, platform)
else:
logger.Error("No source file.")