From 683c1dc245a68742c26de9dfc9329900f69c0926 Mon Sep 17 00:00:00 2001 From: David Chu Date: Mon, 1 Jan 2024 22:40:55 -0500 Subject: [PATCH 1/2] Rename prototype to compiler --- {prototype => compiler}/README.md | 0 {prototype => compiler}/__init__.py | 0 .../analyzer/deprecated/builtins.py | 0 .../analyzer/deprecated/c_builtins/libc.py | 0 .../analyzer/deprecated/c_keywords.py | 0 .../analyzer/deprecated/lol_analyzer.py | 4 +- .../deprecated/lol_analyzer_reserved_names.py | 0 .../analyzer/deprecated/lol_analyzer_types.py | 4 +- .../deprecated/lol_analyzer_user_types.py | 4 +- .../analyzer/new_lol_analyzer.py | 6 +- .../emitter/lol_emitter.py | 2 +- {prototype => compiler}/error/__init__.py | 0 {prototype => compiler}/error/lol_error.py | 0 .../examples/fibonacci.lol | 26 +- .../examples/helloworld.lol | 12 +- .../invalid/duplicate_function_names.lol | 0 {prototype => compiler}/lexer/__init__.py | 0 {prototype => compiler}/lexer/lol_lexer.py | 0 .../lexer/lol_lexer_types.py | 0 {prototype => compiler}/lol.py | 266 +++++++++--------- {prototype => compiler}/parser/__init__.py | 0 {prototype => compiler}/parser/lol_parser.py | 8 +- .../parser/lol_parser_token_stream.py | 2 +- .../parser/lol_parser_types.py | 2 +- 24 files changed, 168 insertions(+), 168 deletions(-) rename {prototype => compiler}/README.md (100%) rename {prototype => compiler}/__init__.py (100%) rename {prototype => compiler}/analyzer/deprecated/builtins.py (100%) rename {prototype => compiler}/analyzer/deprecated/c_builtins/libc.py (100%) rename {prototype => compiler}/analyzer/deprecated/c_keywords.py (100%) rename {prototype => compiler}/analyzer/deprecated/lol_analyzer.py (96%) rename {prototype => compiler}/analyzer/deprecated/lol_analyzer_reserved_names.py (100%) rename {prototype => compiler}/analyzer/deprecated/lol_analyzer_types.py (99%) rename {prototype => compiler}/analyzer/deprecated/lol_analyzer_user_types.py (94%) rename {prototype => compiler}/analyzer/new_lol_analyzer.py (99%) rename {prototype => compiler}/emitter/lol_emitter.py (98%) rename {prototype => compiler}/error/__init__.py (100%) rename {prototype => compiler}/error/lol_error.py (100%) rename {prototype => compiler}/examples/fibonacci.lol (96%) rename {prototype => compiler}/examples/helloworld.lol (95%) rename {prototype => compiler}/examples/invalid/duplicate_function_names.lol (100%) rename {prototype => compiler}/lexer/__init__.py (100%) rename {prototype => compiler}/lexer/lol_lexer.py (100%) rename {prototype => compiler}/lexer/lol_lexer_types.py (100%) rename {prototype => compiler}/lol.py (89%) rename {prototype => compiler}/parser/__init__.py (100%) rename {prototype => compiler}/parser/lol_parser.py (98%) rename {prototype => compiler}/parser/lol_parser_token_stream.py (94%) rename {prototype => compiler}/parser/lol_parser_types.py (99%) diff --git a/prototype/README.md b/compiler/README.md similarity index 100% rename from prototype/README.md rename to compiler/README.md diff --git a/prototype/__init__.py b/compiler/__init__.py similarity index 100% rename from prototype/__init__.py rename to compiler/__init__.py diff --git a/prototype/analyzer/deprecated/builtins.py b/compiler/analyzer/deprecated/builtins.py similarity index 100% rename from prototype/analyzer/deprecated/builtins.py rename to compiler/analyzer/deprecated/builtins.py diff --git a/prototype/analyzer/deprecated/c_builtins/libc.py b/compiler/analyzer/deprecated/c_builtins/libc.py similarity index 100% rename from prototype/analyzer/deprecated/c_builtins/libc.py rename to compiler/analyzer/deprecated/c_builtins/libc.py diff --git a/prototype/analyzer/deprecated/c_keywords.py b/compiler/analyzer/deprecated/c_keywords.py similarity index 100% rename from prototype/analyzer/deprecated/c_keywords.py rename to compiler/analyzer/deprecated/c_keywords.py diff --git a/prototype/analyzer/deprecated/lol_analyzer.py b/compiler/analyzer/deprecated/lol_analyzer.py similarity index 96% rename from prototype/analyzer/deprecated/lol_analyzer.py rename to compiler/analyzer/deprecated/lol_analyzer.py index c5c148e..acf16a4 100644 --- a/prototype/analyzer/deprecated/lol_analyzer.py +++ b/compiler/analyzer/deprecated/lol_analyzer.py @@ -1,10 +1,10 @@ from typing import Dict, List -from prototype.analyzer.lol_analyzer_types import ( +from compiler.analyzer.lol_analyzer_types import ( LolAnalysisObj, LolModule, ) -from prototype.parser.lol_parser import ( +from compiler.parser.lol_parser import ( ASTNode, FunctionDefinitionNode, ImportModuleNode, diff --git a/prototype/analyzer/deprecated/lol_analyzer_reserved_names.py b/compiler/analyzer/deprecated/lol_analyzer_reserved_names.py similarity index 100% rename from prototype/analyzer/deprecated/lol_analyzer_reserved_names.py rename to compiler/analyzer/deprecated/lol_analyzer_reserved_names.py diff --git a/prototype/analyzer/deprecated/lol_analyzer_types.py b/compiler/analyzer/deprecated/lol_analyzer_types.py similarity index 99% rename from prototype/analyzer/deprecated/lol_analyzer_types.py rename to compiler/analyzer/deprecated/lol_analyzer_types.py index e23c693..21bcb8c 100644 --- a/prototype/analyzer/deprecated/lol_analyzer_types.py +++ b/compiler/analyzer/deprecated/lol_analyzer_types.py @@ -2,8 +2,8 @@ from enum import Enum, auto, unique from typing import Any, Dict, List, Set, Union -import prototype.parser.lol_parser_types as parser_types -from prototype.analyzer.c_keywords import SymbolSource, C_KEYWORDS +import compiler.parser.lol_parser_types as parser_types +from compiler.analyzer.c_keywords import SymbolSource, C_KEYWORDS @unique diff --git a/prototype/analyzer/deprecated/lol_analyzer_user_types.py b/compiler/analyzer/deprecated/lol_analyzer_user_types.py similarity index 94% rename from prototype/analyzer/deprecated/lol_analyzer_user_types.py rename to compiler/analyzer/deprecated/lol_analyzer_user_types.py index 9d53e98..202a90b 100644 --- a/prototype/analyzer/deprecated/lol_analyzer_user_types.py +++ b/compiler/analyzer/deprecated/lol_analyzer_user_types.py @@ -1,4 +1,4 @@ -from prototype.analyzer.lol_analyzer_types import LolModule +from compiler.analyzer.lol_analyzer_types import LolModule class LolUserModule(LolModule): @@ -32,7 +32,7 @@ def add_builtin_func(self, name: str): self.symbol_table[name] = LolFunction(name, is_builtin_c=True) def include_stdio(self, lol_alias: str): - from prototype.analyzer.lol_analyzer_reserved_names import STDIO_H_NAMES + from compiler.analyzer.lol_analyzer_reserved_names import STDIO_H_NAMES lib_name = "" if lib_name in self.c_includes: diff --git a/prototype/analyzer/new_lol_analyzer.py b/compiler/analyzer/new_lol_analyzer.py similarity index 99% rename from prototype/analyzer/new_lol_analyzer.py rename to compiler/analyzer/new_lol_analyzer.py index 3319478..4a113b6 100644 --- a/prototype/analyzer/new_lol_analyzer.py +++ b/compiler/analyzer/new_lol_analyzer.py @@ -1,14 +1,14 @@ from typing import Any, Dict, Tuple, List, Optional, Union from enum import Enum, auto, unique -from prototype.parser.lol_parser import ( +from compiler.parser.lol_parser import ( ASTNode, FunctionDefinitionNode, ImportModuleNode, VariableDefinitionNode, ) -import prototype.parser.lol_parser_types as parser_types -import prototype.lexer.lol_lexer_types as lexer_types +import compiler.parser.lol_parser_types as parser_types +import compiler.lexer.lol_lexer_types as lexer_types ################################################################################ diff --git a/prototype/emitter/lol_emitter.py b/compiler/emitter/lol_emitter.py similarity index 98% rename from prototype/emitter/lol_emitter.py rename to compiler/emitter/lol_emitter.py index f63d844..9e819a3 100644 --- a/prototype/emitter/lol_emitter.py +++ b/compiler/emitter/lol_emitter.py @@ -7,7 +7,7 @@ 1. Minimal Viable Product 2. Correct indentation """ -from prototype.analyzer.new_lol_analyzer import ( +from compiler.analyzer.new_lol_analyzer import ( LolAnalysisModule, LolAnalysisFunction, LolAnalysisBuiltinType, LolIRReturnStatement, LolIRFunctionCallStatement, LolIRDefinitionStatement, LolIRSetStatement, LolIRExpression, diff --git a/prototype/error/__init__.py b/compiler/error/__init__.py similarity index 100% rename from prototype/error/__init__.py rename to compiler/error/__init__.py diff --git a/prototype/error/lol_error.py b/compiler/error/lol_error.py similarity index 100% rename from prototype/error/lol_error.py rename to compiler/error/lol_error.py diff --git a/prototype/examples/fibonacci.lol b/compiler/examples/fibonacci.lol similarity index 96% rename from prototype/examples/fibonacci.lol rename to compiler/examples/fibonacci.lol index ae34c8b..92d5a61 100644 --- a/prototype/examples/fibonacci.lol +++ b/compiler/examples/fibonacci.lol @@ -1,13 +1,13 @@ -### Recursive Fibonacci Sequence -module io = import("stdio.h"); - -function fibonacci(n: int64) -> int64 { - return fibonacci(n - 1) + fibonacci(n - 2); -} - -function main() -> int64 { - let result: int64 = fibonacci(10); - # I do not like copying the printf semantics from C... - io::stdout("fibonacci(10) = %l\n", result); - return 0; -} +### Recursive Fibonacci Sequence +module io = import("stdio.h"); + +function fibonacci(n: int64) -> int64 { + return fibonacci(n - 1) + fibonacci(n - 2); +} + +function main() -> int64 { + let result: int64 = fibonacci(10); + # I do not like copying the printf semantics from C... + io::stdout("fibonacci(10) = %l\n", result); + return 0; +} diff --git a/prototype/examples/helloworld.lol b/compiler/examples/helloworld.lol similarity index 95% rename from prototype/examples/helloworld.lol rename to compiler/examples/helloworld.lol index cc6a261..1d93ba2 100644 --- a/prototype/examples/helloworld.lol +++ b/compiler/examples/helloworld.lol @@ -1,7 +1,7 @@ -### Basic hello world -module io = import("stdio.h"); - -function main() -> i32 { - io::printf("Hello, World!\n"); - return 0; +### Basic hello world +module io = import("stdio.h"); + +function main() -> i32 { + io::printf("Hello, World!\n"); + return 0; } \ No newline at end of file diff --git a/prototype/examples/invalid/duplicate_function_names.lol b/compiler/examples/invalid/duplicate_function_names.lol similarity index 100% rename from prototype/examples/invalid/duplicate_function_names.lol rename to compiler/examples/invalid/duplicate_function_names.lol diff --git a/prototype/lexer/__init__.py b/compiler/lexer/__init__.py similarity index 100% rename from prototype/lexer/__init__.py rename to compiler/lexer/__init__.py diff --git a/prototype/lexer/lol_lexer.py b/compiler/lexer/lol_lexer.py similarity index 100% rename from prototype/lexer/lol_lexer.py rename to compiler/lexer/lol_lexer.py diff --git a/prototype/lexer/lol_lexer_types.py b/compiler/lexer/lol_lexer_types.py similarity index 100% rename from prototype/lexer/lol_lexer_types.py rename to compiler/lexer/lol_lexer_types.py diff --git a/prototype/lol.py b/compiler/lol.py similarity index 89% rename from prototype/lol.py rename to compiler/lol.py index 21545f7..5a32edf 100644 --- a/prototype/lol.py +++ b/compiler/lol.py @@ -1,133 +1,133 @@ -import argparse -import json -import os -import time -from typing import Any, Dict, List - -from prototype.lexer.lol_lexer_types import Token -from prototype.parser.lol_parser_token_stream import TokenStream -from prototype.parser.lol_parser_types import ASTNode - -from prototype.lexer.lol_lexer import tokenize -from prototype.parser.lol_parser import parse -from prototype.analyzer.new_lol_analyzer import analyze -from prototype.emitter.lol_emitter import emit_c - - -class LolSymbol: - def __init__(self): - self.type: Any = None - self.definition: Any = None - - def to_dict(self) -> Dict[str, Any]: - return {"type": self.type, } - - -class LolModule: - def __init__(self): - # Metadata - self.init_timestamp = time.time() - - self.text: str = "" - self.tokens: List[Token] = [] - self.ast: List[ASTNode] = [] - self.symbol_table: Dict[str, LolSymbol] = {} - - def read_file(self, file_name: str): - assert isinstance(file_name, str) - with open(file_name) as f: - self.text = f.read() - - ############################################################################ - ### LEXER - ############################################################################ - - def run_lexer(self): - assert self.text != "", "LolModule" - assert self.tokens == [] - - self.tokens = tokenize(self.text) - - def save_lexer_output_only(self, output_dir: str): - file_name: str = f"{output_dir}/{self.init_timestamp}-lexer-output-only.json" - with open(file_name, "w") as f: - json.dump({"lexer-output": [x.to_dict() for x in self.tokens]}, f, indent=4) - - ############################################################################ - ### PARSER - ############################################################################ - - def run_parser(self): - assert self.tokens != [] - - stream = TokenStream(self.tokens, self.text) - self.ast = parse(stream) - - def save_parser_output_only(self, output_dir: str): - file_name: str = f"{output_dir}/{self.init_timestamp}-parser-output-only.json" - with open(file_name, "w") as f: - json.dump({"parser-output": [x.to_dict() for x in self.ast]}, f, indent=4) - - ############################################################################ - ### ANALYZER - ############################################################################ - - def run_analyzer(self): - self.symbol_table = analyze(self.ast, self.text) - - def save_analyzer_output_only(self, output_dir: str): - file_name: str = f"{output_dir}/{self.init_timestamp}-analyzer-output-only.json" - with open(file_name, "w") as f: - json.dump({"analyzer-output": {x: y.to_dict() for x, y in self.symbol_table.module_symbol_table.items()}}, f, indent=4) - - ############################################################################ - ### EMITTER - ############################################################################ - - def run_emitter(self): - # TODO: Make this in the __init__function - self.code = emit_c(self.symbol_table) - - def save_emitter_output_only(self, output_dir: str): - file_name: str = f"{output_dir}/{self.init_timestamp}-emitter-output-only.json" - with open(file_name, "w") as f: - json.dump({"emitter-output": self.code}, f, indent=4) - - - -def main() -> None: - parser = argparse.ArgumentParser() - # TODO(dchu): make this accept multiple file names or folders. Also accept - # a full configuration file. - parser.add_argument( - "-i", "--input", type=str, required=True, help="Input file name" - ) - parser.add_argument( - "-o", "--output", type=str, default=None, help="Output directory name" - ) - args = parser.parse_args() - - # I explicitly extract the names because otherwise one may be tempted to - # pass the 'args' namespace, which is always confusing. - input_file = args.input - output_dir = args.output - - module = LolModule() - # Assume input_file is not None because it is required - module.read_file(input_file) - # Make empty output dir if it doesn't exist - if not os.path.exists(output_dir): - os.mkdir(output_dir) - - module.run_lexer() - module.save_lexer_output_only(output_dir) - module.run_parser() - module.save_parser_output_only(output_dir) - module.run_analyzer() - module.save_analyzer_output_only(output_dir) - module.run_emitter() - module.save_emitter_output_only(output_dir) - - -if __name__ == "__main__": - main() +import argparse +import json +import os +import time +from typing import Any, Dict, List + +from compiler.lexer.lol_lexer_types import Token +from compiler.parser.lol_parser_token_stream import TokenStream +from compiler.parser.lol_parser_types import ASTNode + +from compiler.lexer.lol_lexer import tokenize +from compiler.parser.lol_parser import parse +from compiler.analyzer.new_lol_analyzer import analyze +from compiler.emitter.lol_emitter import emit_c + + +class LolSymbol: + def __init__(self): + self.type: Any = None + self.definition: Any = None + + def to_dict(self) -> Dict[str, Any]: + return {"type": self.type, } + + +class LolModule: + def __init__(self): + # Metadata + self.init_timestamp = time.time() + + self.text: str = "" + self.tokens: List[Token] = [] + self.ast: List[ASTNode] = [] + self.symbol_table: Dict[str, LolSymbol] = {} + + def read_file(self, file_name: str): + assert isinstance(file_name, str) + with open(file_name) as f: + self.text = f.read() + + ############################################################################ + ### LEXER + ############################################################################ + + def run_lexer(self): + assert self.text != "", "LolModule" + assert self.tokens == [] + + self.tokens = tokenize(self.text) + + def save_lexer_output_only(self, output_dir: str): + file_name: str = f"{output_dir}/{self.init_timestamp}-lexer-output-only.json" + with open(file_name, "w") as f: + json.dump({"lexer-output": [x.to_dict() for x in self.tokens]}, f, indent=4) + + ############################################################################ + ### PARSER + ############################################################################ + + def run_parser(self): + assert self.tokens != [] + + stream = TokenStream(self.tokens, self.text) + self.ast = parse(stream) + + def save_parser_output_only(self, output_dir: str): + file_name: str = f"{output_dir}/{self.init_timestamp}-parser-output-only.json" + with open(file_name, "w") as f: + json.dump({"parser-output": [x.to_dict() for x in self.ast]}, f, indent=4) + + ############################################################################ + ### ANALYZER + ############################################################################ + + def run_analyzer(self): + self.symbol_table = analyze(self.ast, self.text) + + def save_analyzer_output_only(self, output_dir: str): + file_name: str = f"{output_dir}/{self.init_timestamp}-analyzer-output-only.json" + with open(file_name, "w") as f: + json.dump({"analyzer-output": {x: y.to_dict() for x, y in self.symbol_table.module_symbol_table.items()}}, f, indent=4) + + ############################################################################ + ### EMITTER + ############################################################################ + + def run_emitter(self): + # TODO: Make this in the __init__function + self.code = emit_c(self.symbol_table) + + def save_emitter_output_only(self, output_dir: str): + file_name: str = f"{output_dir}/{self.init_timestamp}-emitter-output-only.json" + with open(file_name, "w") as f: + json.dump({"emitter-output": self.code}, f, indent=4) + + + +def main() -> None: + parser = argparse.ArgumentParser() + # TODO(dchu): make this accept multiple file names or folders. Also accept + # a full configuration file. + parser.add_argument( + "-i", "--input", type=str, required=True, help="Input file name" + ) + parser.add_argument( + "-o", "--output", type=str, default=None, help="Output directory name" + ) + args = parser.parse_args() + + # I explicitly extract the names because otherwise one may be tempted to + # pass the 'args' namespace, which is always confusing. + input_file = args.input + output_dir = args.output + + module = LolModule() + # Assume input_file is not None because it is required + module.read_file(input_file) + # Make empty output dir if it doesn't exist + if not os.path.exists(output_dir): + os.mkdir(output_dir) + + module.run_lexer() + module.save_lexer_output_only(output_dir) + module.run_parser() + module.save_parser_output_only(output_dir) + module.run_analyzer() + module.save_analyzer_output_only(output_dir) + module.run_emitter() + module.save_emitter_output_only(output_dir) + + +if __name__ == "__main__": + main() diff --git a/prototype/parser/__init__.py b/compiler/parser/__init__.py similarity index 100% rename from prototype/parser/__init__.py rename to compiler/parser/__init__.py diff --git a/prototype/parser/lol_parser.py b/compiler/parser/lol_parser.py similarity index 98% rename from prototype/parser/lol_parser.py rename to compiler/parser/lol_parser.py index 5632aff..695bb1a 100644 --- a/prototype/parser/lol_parser.py +++ b/compiler/parser/lol_parser.py @@ -13,9 +13,9 @@ """ from typing import List, Set, Union -from prototype.lexer.lol_lexer import Token, TokenType -from prototype.parser.lol_parser_token_stream import TokenStream -from prototype.parser.lol_parser_types import ( +from compiler.lexer.lol_lexer import Token, TokenType +from compiler.parser.lol_parser_token_stream import TokenStream +from compiler.parser.lol_parser_types import ( OperatorType, # AST Nodes ASTNode, @@ -45,7 +45,7 @@ # Inner Function Expressions ReturnNode, ) -from prototype.error.lol_error import print_parser_error +from compiler.error.lol_error import print_parser_error LITERAL_TOKENS: Set[TokenType] = {TokenType.DEC, TokenType.STRING} diff --git a/prototype/parser/lol_parser_token_stream.py b/compiler/parser/lol_parser_token_stream.py similarity index 94% rename from prototype/parser/lol_parser_token_stream.py rename to compiler/parser/lol_parser_token_stream.py index a7dd0f7..5d7ce97 100644 --- a/prototype/parser/lol_parser_token_stream.py +++ b/compiler/parser/lol_parser_token_stream.py @@ -1,6 +1,6 @@ from typing import List -from prototype.lexer.lol_lexer import Token +from compiler.lexer.lol_lexer import Token class TokenStream: diff --git a/prototype/parser/lol_parser_types.py b/compiler/parser/lol_parser_types.py similarity index 99% rename from prototype/parser/lol_parser_types.py rename to compiler/parser/lol_parser_types.py index a092927..c3541db 100644 --- a/prototype/parser/lol_parser_types.py +++ b/compiler/parser/lol_parser_types.py @@ -2,7 +2,7 @@ from enum import Enum, auto, unique from typing import List, Tuple, Union -from prototype.lexer.lol_lexer import Token +from compiler.lexer.lol_lexer import Token @unique From d0e809dd274e0d293b1802071c3e0d1fc3265115 Mon Sep 17 00:00:00 2001 From: David Chu Date: Mon, 1 Jan 2024 22:42:26 -0500 Subject: [PATCH 2/2] Ignore --- .gitignore | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f858fab..5a4add7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,14 @@ -# Ignore VS Code directory +# Ignore PyCharm and VS Code directory +.idea .vscode/ # Ignore Python Venv .venv/ venv/ +# Ignore Python Caches +compiler/results +__pycache__/ + # Ignore CMake's build directory build/ cmake/