Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename prototype to compiler #62

Merged
merged 2 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -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/
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from prototype.analyzer.lol_analyzer_types import LolModule
from compiler.analyzer.lol_analyzer_types import LolModule


class LolUserModule(LolModule):
Expand Down Expand Up @@ -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 = "<stdio.h>"
if lib_name in self.c_includes:
Expand Down
Original file line number Diff line number Diff line change
@@ -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


################################################################################
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
266 changes: 133 additions & 133 deletions prototype/lol.py → compiler/lol.py
Original file line number Diff line number Diff line change
@@ -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()
File renamed without changes.
Loading
Loading