Skip to content

Commit

Permalink
Cleanup: Split compiler/typecheck.jou into file per type checking step (
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuli authored Jan 10, 2025
1 parent 3eeeb19 commit 4c260aa
Show file tree
Hide file tree
Showing 14 changed files with 605 additions and 533 deletions.
2 changes: 1 addition & 1 deletion Makefile.posix
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jou_stage2: jou_stage1 config.jou
rm -rf compiler/jou_compiled && ./jou_stage1 -o jou_stage2 --linker-flags "$(LDFLAGS)" compiler/main.jou

# Stage 3 of bootstrapping: Compile the Jou compiler with the Jou compiler.
jou: jou_stage2 config.jou $(wildcard compiler/*.jou)
jou: jou_stage2 config.jou $(wildcard compiler/*.jou compiler/*/*.jou)
rm -rf compiler/jou_compiled && ./jou_stage2 -o jou --linker-flags "$(LDFLAGS)" compiler/main.jou

.PHONY: clean
Expand Down
2 changes: 1 addition & 1 deletion Makefile.windows
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jou_stage2.exe: jou_stage1.exe config.jou
rm -rf compiler/jou_compiled && ./jou_stage1.exe -o jou_stage2.exe --linker-flags "$(LDFLAGS)" compiler/main.jou

# Stage 3 of bootstrapping: Compile the Jou compiler with the Jou compiler.
jou.exe: jou_stage2.exe config.jou $(wildcard compiler/*.jou)
jou.exe: jou_stage2.exe config.jou $(wildcard compiler/*.jou compiler/*/*.jou)
rm -rf compiler/jou_compiled && ./jou_stage2.exe -o jou.exe --linker-flags "$(LDFLAGS)" compiler/main.jou

.PHONY: clean
Expand Down
14 changes: 3 additions & 11 deletions compiler/build_cf_graph.jou
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "./cf_graph.jou"
import "./structs.jou"
import "./evaluate.jou"
import "./types.jou"
import "./typecheck/common.jou"
import "./errors_and_warnings.jou"
import "./ast.jou"

Expand Down Expand Up @@ -534,18 +535,9 @@ def build_function_or_method_call(
assert selfclass->kind == TypeKind::Pointer
selfclass = selfclass->value_type
assert selfclass->kind == TypeKind::Class

for s = selfclass->classdata.methods; s < &selfclass->classdata.methods[selfclass->classdata.nmethods]; s++:
assert s->get_self_class() == selfclass
if strcmp(s->name, call->name) == 0:
sig = s
break

sig = selfclass->find_method(call->name)
else:
for f = st->filetypes->functions; f < &st->filetypes->functions[st->filetypes->nfunctions]; f++:
if strcmp(f->signature.name, call->name) == 0:
sig = &f->signature
break
sig = st->filetypes->find_function(call->name)

assert sig != NULL

Expand Down
1 change: 1 addition & 0 deletions compiler/cf_graph.jou
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "stdlib/io.jou"

import "./errors_and_warnings.jou"
import "./structs.jou"
import "./typecheck/common.jou"
import "./print.jou"
import "./free.jou"
import "./types.jou"
Expand Down
1 change: 1 addition & 0 deletions compiler/codegen.jou
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import "stdlib/mem.jou"
import "stdlib/str.jou"

import "./evaluate.jou"
import "./typecheck/common.jou"
import "./cf_graph.jou"
import "./llvm.jou"
import "./target.jou"
Expand Down
6 changes: 6 additions & 0 deletions compiler/evaluate.jou
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import "./ast.jou"
import "./errors_and_warnings.jou"


def evaluate_array_length(expr: AstExpression*) -> int:
if expr->kind == AstExpressionKind::Int:
return expr->int_value
fail(expr->location, "cannot evaluate array length at compile time")


def get_special_constant(name: byte*) -> int:
if strcmp(name, "WINDOWS") == 0:
return WINDOWS as int
Expand Down
4 changes: 3 additions & 1 deletion compiler/free.jou
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Boring boilerplate code to free up data structures used in compilation.

import "stdlib/mem.jou"

import "./structs.jou"
import "./types.jou"
import "./token.jou"
import "stdlib/mem.jou"
import "./typecheck/common.jou"

def free_tokens(tokenlist: Token*) -> None:
for t = tokenlist; t->kind != TokenKind::EndOfFile; t++:
Expand Down
19 changes: 11 additions & 8 deletions compiler/main.jou
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import "./codegen.jou"
import "./print.jou"
import "./llvm.jou"
import "./output.jou"
import "./typecheck.jou"
import "./typecheck/common.jou"
import "./typecheck/step1_create_types.jou"
import "./typecheck/step2_populate_types.jou"
import "./typecheck/step3_function_and_method_bodies.jou"
import "./target.jou"
import "./types.jou"
import "./free.jou"
Expand Down Expand Up @@ -344,7 +347,7 @@ class CompileState:
self->parse(path, NULL)
free(path)

# Each stage of type checking produces exported symbols that other files can import.
# Each step of type checking produces exported symbols that other files can import.
# This method hands them over to the importing files.
def exports_to_imports(self, pending_exports: ExportSymbol**) -> None:
for to = self->files; to < &self->files[self->nfiles]; to++:
Expand Down Expand Up @@ -399,22 +402,22 @@ class CompileState:

for i = 0; i < self->nfiles; i++:
if command_line_args.verbosity >= 1:
printf(" stage 1: %s\n", self->files[i].path)
pending_exports[i] = typecheck_stage1_create_types(&self->files[i].types, &self->files[i].ast)
printf(" step 1: %s\n", self->files[i].path)
pending_exports[i] = typecheck_step1_create_types(&self->files[i].types, &self->files[i].ast)

self->exports_to_imports(pending_exports)

for i = 0; i < self->nfiles; i++:
if command_line_args.verbosity >= 1:
printf(" stage 2: %s\n", self->files[i].path)
pending_exports[i] = typecheck_stage2_populate_types(&self->files[i].types, &self->files[i].ast)
printf(" step 2: %s\n", self->files[i].path)
pending_exports[i] = typecheck_step2_populate_types(&self->files[i].types, &self->files[i].ast)

self->exports_to_imports(pending_exports)

for i = 0; i < self->nfiles; i++:
if command_line_args.verbosity >= 1:
printf(" stage 3: %s\n", self->files[i].path)
typecheck_stage3_function_and_method_bodies(&self->files[i].types, &self->files[i].ast)
printf(" step 3: %s\n", self->files[i].path)
typecheck_step3_function_and_method_bodies(&self->files[i].types, &self->files[i].ast)

free(pending_exports)

Expand Down
78 changes: 0 additions & 78 deletions compiler/structs.jou
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
# TODO: delete this file, merge into others

import "stdlib/str.jou"
import "stdlib/math.jou"
import "stdlib/io.jou"

import "./ast.jou"
import "./types.jou"


Expand Down Expand Up @@ -85,78 +82,3 @@ def int_constant(type: Type*, value: long) -> Constant:
value = value
}
}


class GlobalVariable:
name: byte[100] # Same as in user's code, never empty
type: Type*
defined_in_current_file: bool # not declare-only (e.g. stdout) or imported
usedptr: bool* # If non-NULL, set to true when the variable is used. This is how we detect unused imports.


class LocalVariable:
id: int # Unique, but you can also compare pointers to LocalVariable.
name: byte[100] # Same name as in user's code, empty for temporary variables created by compiler
type: Type*
is_argument: bool # First n variables are always the arguments

def print_to_width(self, width: int) -> None:
if self->name[0] != '\0':
printf("%-*s", width, self->name)
else:
printf("$%-*d", max(width-1, 0), self->id)

def print(self) -> None:
self->print_to_width(0)


class ExpressionTypes:
expr: AstExpression* # not owned
type: Type*
implicit_cast_type: Type* # NULL for no implicit cast

# Flags to indicate whether special kinds of implicit casts happened
implicit_array_to_pointer_cast: bool # Foo[N] to Foo*
implicit_string_to_array_cast: bool # "..." to byte[N]

enum ExportSymbolKind:
Function
Type
GlobalVar

class ExportSymbol:
kind: ExportSymbolKind
name: byte[100] # TODO: maybe this should be 200 because it can be ClassName.method_name? or something else?
union:
funcsignature: Signature
type: Type* # ExportSymbolKind::Type and ExportSymbolKind::GlobalVar

# Type information about a function or method defined in the current file.
class FunctionOrMethodTypes:
signature: Signature
expr_types: ExpressionTypes**
n_expr_types: int
locals: LocalVariable**
nlocals: int

class TypeAndUsedPtr:
type: Type*
usedptr: bool*

class SignatureAndUsedPtr:
signature: Signature
usedptr: bool*

# Type information about a file.
class FileTypes:
current_fom_types: FunctionOrMethodTypes* # conceptually this is internal to typecheck.c
fomtypes: FunctionOrMethodTypes*
nfomtypes: int
globals: GlobalVariable*
nglobals: int
owned_types: Type** # These will be freed later
n_owned_types: int
types: TypeAndUsedPtr*
ntypes: int
functions: SignatureAndUsedPtr*
nfunctions: int
Loading

0 comments on commit 4c260aa

Please sign in to comment.