Skip to content

Commit

Permalink
Combine startup files
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuli committed Dec 6, 2023
1 parent 8a9fd39 commit d90ffbe
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 69 deletions.
10 changes: 10 additions & 0 deletions self_hosted/evaluate.jou
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,22 @@ def get_special_constant(name: byte*) -> int:


def evaluate_condition(expr: AstExpression*) -> bool:
if expr->kind == AstExpressionKind::And:
return evaluate_condition(&expr->operands[0]) and evaluate_condition(&expr->operands[1])

if expr->kind == AstExpressionKind::Or:
return evaluate_condition(&expr->operands[0]) or evaluate_condition(&expr->operands[1])

if expr->kind == AstExpressionKind::Not:
return not evaluate_condition(&expr->operands[0])

if expr->kind == AstExpressionKind::GetVariable:
v = get_special_constant(expr->varname)
if v == 1:
return True
if v == 0:
return False

fail(expr->location, "cannot evaluate condition at compile time")


Expand Down
4 changes: 2 additions & 2 deletions self_hosted/main.jou
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,9 @@ class Compiler:
def determine_automagic_files(self) -> void:
self->automagic_files[0] = malloc(strlen(self->stdlib_path) + 40)
sprintf(self->automagic_files[0], "%s/_assert_fail.jou", self->stdlib_path)
if WINDOWS:
if WINDOWS or MACOS:
self->automagic_files[1] = malloc(strlen(self->stdlib_path) + 40)
sprintf(self->automagic_files[1], "%s/_windows_startup.jou", self->stdlib_path)
sprintf(self->automagic_files[1], "%s/_io_init.jou", self->stdlib_path)

def parse_all_files(self) -> void:
queue: ParseQueueItem* = malloc(50 * sizeof queue[0])
Expand Down
1 change: 0 additions & 1 deletion self_hosted/runs_wrong.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,4 @@ tests/wrong_type/cannot_be_indexed.jou
tests/wrong_type/index.jou
stdlib/ascii.jou
tests/should_succeed/ascii_test.jou
stdlib/_macos_startup.jou
tests/should_succeed/if_WINDOWS_at_runtime.jou
13 changes: 3 additions & 10 deletions src/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,17 +422,10 @@ static int find_block(const CfGraph *cfg, const CfBlock *b)
}

#if defined(_WIN32) || defined(__APPLE__)
static void codegen_call_to_the_special_startup_function(const struct State *st)
static void codegen_call_to_the_special_jou_io_init_function(const struct State *st)
{
const char *name;
#ifdef _WIN32
name = "_jou_windows_startup";
#else
name = "_jou_macos_startup";
#endif

LLVMTypeRef functype = LLVMFunctionType(LLVMVoidType(), NULL, 0, false);
LLVMValueRef func = LLVMAddFunction(st->module, name, functype);
LLVMValueRef func = LLVMAddFunction(st->module, "_jou_io_init", functype);
LLVMBuildCall2(st->builder, functype, func, NULL, 0, "");
}
#endif
Expand All @@ -457,7 +450,7 @@ static void codegen_function_or_method_def(struct State *st, const CfGraph *cfg)

#if defined(_WIN32) || defined(__APPLE__)
if (!get_self_class(&cfg->signature) && !strcmp(cfg->signature.name, "main"))
codegen_call_to_the_special_startup_function(st);
codegen_call_to_the_special_jou_io_init_function(st);
#endif

// Allocate stack space for local variables at start of function.
Expand Down
20 changes: 16 additions & 4 deletions src/evaluate.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,22 @@ int get_special_constant(const char *name)

static bool evaluate_condition(const AstExpression *expr)
{
if (expr->kind == AST_EXPR_GET_VARIABLE) {
int v = get_special_constant(expr->data.varname);
if (v != -1)
return (bool)v;
switch(expr->kind) {
case AST_EXPR_AND:
return evaluate_condition(&expr->data.operands[0]) && evaluate_condition(&expr->data.operands[1]);
case AST_EXPR_OR:
return evaluate_condition(&expr->data.operands[0]) || evaluate_condition(&expr->data.operands[1]);
case AST_EXPR_NOT:
return !evaluate_condition(&expr->data.operands[0]);
case AST_EXPR_GET_VARIABLE:
{
int v = get_special_constant(expr->data.varname);
if (v != -1)
return (bool)v;
break;
}
default:
break;
}

fail(expr->location, "cannot evaluate condition at compile time");
Expand Down
7 changes: 2 additions & 5 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,11 +456,8 @@ int main(int argc, char **argv)
}

include_special_stdlib_file(&compst, "_assert_fail.jou");
#ifdef _WIN32
include_special_stdlib_file(&compst, "_windows_startup.jou");
#endif
#ifdef __APPLE__
include_special_stdlib_file(&compst, "_macos_startup.jou");
#if defined(_WIN32) || defined(__APPLE__)
include_special_stdlib_file(&compst, "_io_init.jou");
#endif

parse_file(&compst, command_line_args.infile, NULL);
Expand Down
46 changes: 46 additions & 0 deletions stdlib/_io_init.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# stdin, stdout and stderr are special files for terminal input and output.
# For example, printf() writes to stdout.
#
# For some random technical reason Windows and MacOS don't have these
# variables. For example, on Windows, when a C program mentions "stdin", the C
# compiler replaces it with "(__acrt_iob_func(0))":
#
# $ sudo apt install gcc-mingw-w64-x86-64
# $ echo -e "#include <stdio.h>\nstdin\nstdout\nstderr" | x86_64-w64-mingw32-cpp | tail -3
# (__acrt_iob_func(0))
# (__acrt_iob_func(1))
# (__acrt_iob_func(2))
#
# On MacOS, there is a similar but slightly different situation: these special
# files are stored in variables, but the variables have different names.
#
# To keep things simple, Jou always provides stdin, stdout and stderr variables.
# When compiling for Windows or MacOS, the compiler magically adds a call to
# _jou_io_init() to the beginning of main() on Windows and MacOS. You may need
# to call it manually if your project doesn't have a main() function written
# in Jou.


# Use void pointers to avoid dependency on io.jou.
global stdin: void*
global stdout: void*
global stderr: void*

# TODO: assertions at compile time
#assert WINDOWS or MACOS

if WINDOWS:
declare __acrt_iob_func(index: int) -> void*
def _jou_io_init() -> void:
stdin = __acrt_iob_func(0)
stdout = __acrt_iob_func(1)
stderr = __acrt_iob_func(2)

if MACOS:
declare global __stdinp: void*
declare global __stdoutp: void*
declare global __stderrp: void*
def _jou_io_init() -> void:
stdin = __stdinp
stdout = __stdoutp
stderr = __stderrp
20 changes: 0 additions & 20 deletions stdlib/_macos_startup.jou

This file was deleted.

26 changes: 0 additions & 26 deletions stdlib/_windows_startup.jou

This file was deleted.

6 changes: 5 additions & 1 deletion stdlib/io.jou
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ class FILE:
# to accessing the members directly.
_dummy: int

# Special files for terminal input and output.
# stdin, stdout and stderr are special files for terminal input and output.
# For example, printf() writes to stdout.
#
# We use "declare global" because the variables are not defined here. We only
# tell the Jou compiler that they exist. See also _io_init.jou.
declare global stdin: FILE*
declare global stdout: FILE*
declare global stderr: FILE*
Expand Down
20 changes: 20 additions & 0 deletions tests/should_succeed/compile_time_if.jou
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,31 @@ else:
# python uses 777 as default perms, see help(os.mkdir)
mkdir("tmp/tests/foo", 0o777)

# This complicated way to print "foobar" is supposed to test 'and', 'or', 'not'
if WINDOWS or MACOS:
def foo() -> void:
printf("fo")
if not WINDOWS and not MACOS:
def foo() -> void:
printf("foo")

if not (not WINDOWS and not MACOS):
def bar() -> void:
printf("obar\n")
if not (WINDOWS or MACOS):
def bar() -> void:
printf("bar")

def main() -> int:
make_foo()
f = fopen("tmp/tests/foo/bar", "w")
if f != NULL:
puts("ok") # Output: ok
fclose(f)

# Output: foobar
foo()
bar()
printf("\n")

return 0

0 comments on commit d90ffbe

Please sign in to comment.