diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 2617e10..0000000 --- a/.gitignore +++ /dev/null @@ -1,55 +0,0 @@ -# Prerequisites -*.d - -# Object files -*.o -*.ko -*.obj -*.elf - -# Linker output -*.ilk -*.map -*.exp - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex - -# Debug files -*.dSYM/ -*.su -*.idb -*.pdb - -# Kernel Module Compile Results -*.mod* -*.cmd -.tmp_versions/ -modules.order -Module.symvers -Mkfile.old -dkms.conf - -# vscode -.vscode/ \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index c2098a2..f18a699 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,14 +1,14 @@ { "configurations": [ { - "name": "linux-gcc-x64", + "name": "windows-gcc-x64", "includePath": [ "${workspaceFolder}/**" ], - "compilerPath": "/usr/bin/gcc", + "compilerPath": "C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/gcc.exe", "cStandard": "${default}", "cppStandard": "${default}", - "intelliSenseMode": "linux-gcc-x64", + "intelliSenseMode": "windows-gcc-x64", "compilerArgs": [ "" ] diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index bb41346..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "C/C++ Runner: Debug Session", - "type": "cppdbg", - "request": "launch", - "args": [], - "stopAtEntry": false, - "externalConsole": false, - "cwd": "/home/eugene-chevski/Desktop/CodeGeneratorSPL", - "program": "/home/eugene-chevski/Desktop/CodeGeneratorSPL/build/Debug/outDebug", - "MIMode": "gdb", - "miDebuggerPath": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] - } - ] -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index a8aadc4..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "C_Cpp_Runner.cCompilerPath": "gcc", - "C_Cpp_Runner.cppCompilerPath": "g++", - "C_Cpp_Runner.debuggerPath": "gdb", - "C_Cpp_Runner.cStandard": "", - "C_Cpp_Runner.cppStandard": "", - "C_Cpp_Runner.msvcBatchPath": "", - "C_Cpp_Runner.useMsvc": false, - "C_Cpp_Runner.warnings": [ - "-Wall", - "-Wextra", - "-Wpedantic", - "-Wshadow", - "-Wformat=2", - "-Wcast-align", - "-Wconversion", - "-Wsign-conversion", - "-Wnull-dereference" - ], - "C_Cpp_Runner.msvcWarnings": [ - "/W4", - "/permissive-", - "/w14242", - "/w14287", - "/w14296", - "/w14311", - "/w14826", - "/w44062", - "/w44242", - "/w14905", - "/w14906", - "/w14263", - "/w44265", - "/w14928" - ], - "C_Cpp_Runner.enableWarnings": true, - "C_Cpp_Runner.warningsAsError": false, - "C_Cpp_Runner.compilerArgs": [], - "C_Cpp_Runner.linkerArgs": [], - "C_Cpp_Runner.includePaths": [], - "C_Cpp_Runner.includeSearch": [ - "*", - "**/*" - ], - "C_Cpp_Runner.excludeSearch": [ - "**/build", - "**/build/**", - "**/.*", - "**/.*/**", - "**/.vscode", - "**/.vscode/**" - ], - "C_Cpp_Runner.useAddressSanitizer": false, - "C_Cpp_Runner.useUndefinedSanitizer": false, - "C_Cpp_Runner.useLeakSanitizer": false, - "C_Cpp_Runner.showCompilationTime": false, - "C_Cpp_Runner.useLinkTimeOptimization": false, - "C_Cpp_Runner.msvcSecureNoWarnings": false, - "files.associations": { - "gen_code.h": "c" - } -} \ No newline at end of file diff --git a/COP3402_Group_Member_Responsibilities.docx b/COP3402_Group_Member_Responsibilities.docx deleted file mode 100644 index 1d2de48..0000000 Binary files a/COP3402_Group_Member_Responsibilities.docx and /dev/null differ diff --git a/CollaborationFormulas.pdf b/CollaborationFormulas.pdf deleted file mode 100644 index d32b0db..0000000 Binary files a/CollaborationFormulas.pdf and /dev/null differ diff --git a/FromGithub/CopyWork.zip b/FromGithub/CopyWork.zip new file mode 100644 index 0000000..94af7c3 Binary files /dev/null and b/FromGithub/CopyWork.zip differ diff --git a/Makefile b/FromGithub/Makefile old mode 100755 new mode 100644 similarity index 100% rename from Makefile rename to FromGithub/Makefile diff --git a/README.md b/FromGithub/README.md similarity index 100% rename from README.md rename to FromGithub/README.md diff --git a/ast.c b/FromGithub/ast.c old mode 100755 new mode 100644 similarity index 96% rename from ast.c rename to FromGithub/ast.c index 6b15584..257077a --- a/ast.c +++ b/FromGithub/ast.c @@ -1,780 +1,780 @@ -/* $Id: ast.c,v 1.15 2024/11/03 22:49:33 leavens Exp $ */ -#include -#include -#include -#include "utilities.h" -#include "ast.h" -#include "spl.tab.h" - -// Return the file location from an AST -file_location *ast_file_loc(AST t) { - return t.generic.file_loc; -} - -// Return the filename from the AST t -const char *ast_filename(AST t) { - return ast_file_loc(t)->filename; -} - -// Return the line number from the AST t -unsigned int ast_line(AST t) { - return ast_file_loc(t)->line; -} - -// Return the type tag of the AST t -AST_type ast_type_tag(AST t) { - return t.generic.type_tag; -} - -// Return a pointer to a fresh copy of t -// that has been allocated on the heap -AST *ast_heap_copy(AST t) { - AST *ret = (AST *)malloc(sizeof(AST)); - if (ret == NULL) { - bail_with_error("Cannot allocate an AST heap copy!"); - } - *ret = t; - return ret; -} - -// Return an AST for a block which contains the given ASTs. -block_t ast_block(token_t begin_tok, const_decls_t const_decls, - var_decls_t var_decls, proc_decls_t proc_decls, - stmts_t stmts) -{ - block_t ret; - ret.file_loc = file_location_copy(begin_tok.file_loc); - ret.type_tag = block_ast; - ret.const_decls = const_decls; - ret.var_decls = var_decls; - ret.proc_decls = proc_decls; - ret.stmts = stmts; - return ret; -} - -// Return an AST for an empty const decls -extern const_decls_t ast_const_decls_empty(empty_t empty) -{ - const_decls_t ret; - ret.file_loc = empty.file_loc; - ret.type_tag = const_decls_ast; - ret.start = NULL; - return ret; -} - -// Return an AST for the const decls -const_decls_t ast_const_decls(const_decls_t const_decls, - const_decl_t const_decl) -{ - const_decls_t ret = const_decls; - // make a copy of const_decl on the heap - const_decl_t *p = (const_decl_t *) malloc(sizeof(const_decl_t)); - if (p == NULL) { - bail_with_error("Cannot allocate space for %s!", "const_decl_t"); - } - *p = const_decl; - p->next = NULL; - const_decl_t *last = ast_last_list_elem(ret.start); - if (last == NULL) { - ret.start = p; - } else { - last->next = p; - } - return ret; -} - - - -// Return an AST for a const_decl -const_decl_t ast_const_decl(const_def_list_t const_def_list) -{ - const_decl_t ret; - ret.file_loc = const_def_list.file_loc; - ret.type_tag = const_decl_ast; - ret.const_def_list = const_def_list; - ret.next = NULL; - return ret; -} - -// Return an AST for const-def-list that is a singleton -extern const_def_list_t ast_const_def_list_singleton(const_def_t const_def) -{ - const_def_list_t ret; - ret.file_loc = const_def.file_loc; - ret.type_tag = const_def_list_ast; - const_def_t *p = (const_def_t *) malloc(sizeof(const_def_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "const_def_t"); - } - *p = const_def; - p->next = NULL; - ret.start = p; - return ret; -} - -// Return an AST for const_defs -extern const_def_list_t ast_const_def_list(const_def_list_t const_def_list, - const_def_t const_def) -{ - const_def_list_t ret = const_def_list; - // make a copy of const_def on the heap - const_def_t *p = (const_def_t *) malloc(sizeof(const_def_t)); - if (p == NULL) { - bail_with_error("Cannot allocate space for %s!", "const_def_t"); - } - *p = const_def; - p->next = NULL; - const_def_t *last = ast_last_list_elem(ret.start); - if (last == NULL) { - ret.start = p; - } else { - last->next = p; - } - return ret; -} - -// Return an AST for a const-def -const_def_t ast_const_def(ident_t ident, number_t number) -{ - const_def_t ret; - ret.file_loc = file_location_copy(ident.file_loc); - assert((ret.file_loc)->filename != NULL); - ret.type_tag = const_def_ast; - ret.next = NULL; - ret.ident = ident; - ret.number = number; - return ret; -} - - -// Return an AST for varDecls that are empty -var_decls_t ast_var_decls_empty(empty_t empty) -{ - var_decls_t ret; - ret.file_loc = empty.file_loc; - ret.type_tag = var_decls_ast; - ret.var_decls = NULL; - return ret; -} - -// Return an AST varDecls that have some var_decls -var_decls_t ast_var_decls(var_decls_t var_decls, var_decl_t var_decl) -{ - var_decls_t ret = var_decls; - // make a copy of var_decl on the heap - var_decl_t *p = (var_decl_t *) malloc(sizeof(var_decl_t)); - if (p == NULL) { - bail_with_error("Cannot allocate space for %s!", "var_decl_t"); - } - *p = var_decl; - p->next = NULL; - var_decl_t *last = ast_last_list_elem(ret.var_decls); - if (last == NULL) { - ret.var_decls = p; - } else { - last->next = p; - } - return ret; -} - -// Return an AST for a var_decl -var_decl_t ast_var_decl(ident_list_t ident_list) -{ - var_decl_t ret; - ret.file_loc = ident_list.file_loc; - ret.type_tag = var_decl_ast; - ret.next = NULL; - ret.ident_list = ident_list; - return ret; -} - -// Return an AST made for one ident -extern ident_list_t ast_ident_list_singleton(ident_t ident) -{ - ident_list_t ret; - ret.file_loc = ident.file_loc; - ret.type_tag = ident_list_ast; - // make a copy of ident on the heap - ident_t *p = (ident_t *) malloc(sizeof(ident_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "ident_t"); - } - *p = ident; - p->next = NULL; - ret.start = p; - return ret; -} - -// Return an AST made for idents -extern ident_list_t ast_ident_list(ident_list_t ident_list, ident_t ident) -{ - ident_list_t ret = ident_list; - // make a copy of ident on the heap - ident_t *p = (ident_t *) malloc(sizeof(ident_t)); - if (p == NULL) { - bail_with_error("Cannot allocate space for %s!", "ident_t"); - } - *p = ident; - p->next = NULL; - ident_t *last = ast_last_list_elem(ret.start); - if (last == NULL) { - ret.start = p; - } else { - last->next = p; - } - return ret; -} - -// Return an AST for proc_decls -proc_decls_t ast_proc_decls_empty(empty_t empty) -{ - proc_decls_t ret; - ret.file_loc = empty.file_loc; - ret.type_tag = proc_decls_ast; - ret.proc_decls = NULL; - return ret; -} - -// Return an AST for proc_decls -proc_decls_t ast_proc_decls(proc_decls_t proc_decls, - proc_decl_t proc_decl) -{ - proc_decls_t ret = proc_decls; - // make a copy of proc_decl on the heap - proc_decl_t *p = (proc_decl_t *) malloc(sizeof(proc_decl_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "proc_decl_t"); - } - *p = proc_decl; - p->next = NULL; - proc_decl_t *last = ast_last_list_elem(ret.proc_decls); - if (last == NULL) { - ret.proc_decls = p; - } else { - last->next = p; - } - return ret; -} - -// Return an AST for a proc_decl -proc_decl_t ast_proc_decl(ident_t ident, block_t block) -{ - proc_decl_t ret; - ret.file_loc = file_location_copy(ident.file_loc); - ret.type_tag = proc_decl_ast; - ret.next = NULL; - ret.name = ident.name; - block_t *p = (block_t *) malloc(sizeof(block_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "block_t"); - } - *p = block; - ret.block = p; - return ret; -} - -// Return an AST for a print statement -print_stmt_t ast_print_stmt(expr_t expr) { - print_stmt_t ret; - ret.file_loc = expr.file_loc; - ret.type_tag = print_stmt_ast; - ret.expr = expr; - return ret; -} - -// Return an AST for a read statement -read_stmt_t ast_read_stmt(ident_t ident) { - read_stmt_t ret; - ret.file_loc = file_location_copy(ident.file_loc); - ret.type_tag = read_stmt_ast; - ret.name = ident.name; - return ret; -} - -// Return an immediate data holding an address -while_stmt_t ast_while_stmt(condition_t condition, stmts_t body) { - while_stmt_t ret; - ret.file_loc = condition.file_loc; - ret.type_tag = while_stmt_ast; - ret.condition = condition; - stmts_t *p = (stmts_t *) malloc(sizeof(stmts_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "stmts_t"); - } - *p = body; - ret.body = p; - return ret; -} - -// Return an AST for an if-then-else statement -if_stmt_t ast_if_then_else_stmt(condition_t condition, - stmts_t then_stmts, stmts_t else_stmts) -{ - if_stmt_t ret; - ret.file_loc = condition.file_loc; - ret.type_tag = if_stmt_ast; - ret.condition = condition; - // copy then_stmt to the heap - stmts_t *p = (stmts_t *) malloc(sizeof(stmts_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "stmts_t"); - } - *p = then_stmts; - ret.then_stmts = p; - // copy else_stmts to the heap - p = (stmts_t *) malloc(sizeof(stmts_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "stmts_t"); - } - *p = else_stmts; - ret.else_stmts = p; - return ret; -} - -// Return an AST for a (short) if-then statement -// Note that the else part is a NULL pointer -extern if_stmt_t ast_if_then_stmt(condition_t condition, - stmts_t then_stmts) -{ - if_stmt_t ret; - ret.file_loc = condition.file_loc; - ret.type_tag = if_stmt_ast; - ret.condition = condition; - // copy then_stmt to the heap - stmts_t *p = (stmts_t *) malloc(sizeof(stmts_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "stmts_t"); - } - *p = then_stmts; - ret.then_stmts = p; - ret.else_stmts = NULL; - return ret; -} - -// Return an AST for a begin statement -// containing the given list of statements -block_stmt_t ast_block_stmt(block_t block) -{ - block_stmt_t ret; - ret.file_loc = block.file_loc; - ret.type_tag = block_stmt_ast; - // copy the block to the heap - block_t *p = (block_t *) malloc(sizeof(block_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "block_t"); - } - *p = block; - ret.block = p; - return ret; -} - -// Return an AST for a call statment - call_stmt_t ast_call_stmt(ident_t ident) -{ - call_stmt_t ret; - ret.file_loc = file_location_copy(ident.file_loc); - ret.type_tag = call_stmt_ast; - ret.name = ident.name; - return ret; -} - -// Return an AST for an assignment statement -assign_stmt_t ast_assign_stmt(ident_t ident, expr_t expr) -{ - assign_stmt_t ret; - ret.file_loc = file_location_copy(ident.file_loc); - ret.type_tag = assign_stmt_ast; - ret.name = ident.name; - assert(ret.name != NULL); - expr_t *p = (expr_t *) malloc(sizeof(expr_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "expr_t"); - } - *p = expr; - ret.expr = p; - assert(ret.expr != NULL); - return ret; -} - -// Return an AST for the list of statements -stmts_t ast_stmts_empty(empty_t empty) -{ - stmts_t ret; - ret.file_loc = file_location_copy(empty.file_loc); - ret.type_tag = stmts_ast; - ret.stmts_kind = empty_stmts_e; - return ret; -} - -// Return an AST for empty found in the given file location -empty_t ast_empty(file_location *file_loc) -{ - empty_t ret; - ret.file_loc = file_loc; - ret.type_tag = empty_ast; - return ret; -} - -// Return an AST for the list of statements -stmts_t ast_stmts(stmt_list_t stmt_list) -{ - stmts_t ret; - ret.file_loc = stmt_list.file_loc; - ret.type_tag = stmts_ast; - ret.stmts_kind = stmt_list_e; - ret.stmt_list = stmt_list; - return ret; -} - - -// Return an AST for the list of statements -stmt_list_t ast_stmt_list_singleton(stmt_t stmt) { - // debug_print("Entering ast_stmts_singleton\n"); - stmt_list_t ret; - ret.file_loc = stmt.file_loc; - ret.type_tag = stmt_list_ast; - stmt.next = NULL; - // copy stmt to the heap - stmt_t *p = (stmt_t *) malloc(sizeof(stmt_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "stmt_t"); - } - *p = stmt; - p->next = NULL; - // there will be no statments after stmt in the list - ret.start = p; - return ret; -} - -// Return an AST for the list of statements -extern stmt_list_t ast_stmt_list(stmt_list_t stmt_list, stmt_t stmt) { - // debug_print("Entering ast_stmt_list...\n"); - stmt_list_t ret = stmt_list; - // copy stmt to the heap - stmt_t *s = (stmt_t *) malloc(sizeof(stmt_t)); - if (s == NULL) { - bail_with_error("Cannot allocate space for %s!", "stmt_t"); - } - *s = stmt; - s->next = NULL; - stmt_t *last = ast_last_list_elem(ret.start); - assert(last != NULL); // because there are no empty lists of stmts - last->next = s; - return ret; -} - -// Return an AST for the given statment -stmt_t ast_stmt_assign(assign_stmt_t s) -{ - stmt_t ret; - ret.file_loc = s.file_loc; - ret.type_tag = stmt_ast; - ret.next = NULL; - ret.stmt_kind = assign_stmt; - ret.data.assign_stmt = s; - return ret; -} - -// Return an AST for the given statment -stmt_t ast_stmt_call(call_stmt_t s) -{ - stmt_t ret; - ret.file_loc = s.file_loc; - ret.type_tag = stmt_ast; - ret.next = NULL; - ret.stmt_kind = call_stmt; - ret.data.call_stmt = s; - return ret; -} - -// Return an AST for the given statment -stmt_t ast_stmt_block(block_stmt_t s) -{ - stmt_t ret; - ret.file_loc = s.file_loc; - ret.type_tag = stmt_ast; - ret.next = NULL; - ret.stmt_kind = block_stmt; - ret.data.block_stmt = s; - return ret; -} - -// Return an AST for the given statment -stmt_t ast_stmt_if(if_stmt_t s) -{ - stmt_t ret; - ret.file_loc = s.file_loc; - ret.type_tag = stmt_ast; - ret.next = NULL; - ret.stmt_kind = if_stmt; - ret.data.if_stmt = s; - return ret; -} - -// Return an AST for the given statment -stmt_t ast_stmt_while(while_stmt_t s) -{ - stmt_t ret; - ret.file_loc = s.file_loc; - ret.type_tag = stmt_ast; - ret.next = NULL; - ret.stmt_kind = while_stmt; - ret.data.while_stmt = s; - return ret; -} - -// Return an AST for the given statment -stmt_t ast_stmt_read(read_stmt_t s) -{ - stmt_t ret; - ret.file_loc = s.file_loc; - ret.type_tag = stmt_ast; - ret.next = NULL; - ret.stmt_kind = read_stmt; - ret.data.read_stmt = s; - return ret; -} - -// Return an AST for the given statment -stmt_t ast_stmt_print(print_stmt_t s) -{ - // debug_print("Entering ast_stmt_print...\n"); - stmt_t ret; - ret.file_loc = s.file_loc; - ret.type_tag = stmt_ast; - ret.next = NULL; - ret.stmt_kind = print_stmt; - ret.data.print_stmt = s; - return ret; -} - -// Return an AST for an odd condition -db_condition_t ast_db_condition(expr_t dividend, expr_t divisor) -{ - db_condition_t ret; - ret.file_loc = dividend.file_loc; - ret.type_tag = db_condition_ast; - ret.dividend = dividend; - ret.divisor = divisor; - return ret; -} - -// Return an AST for an initializer with the given value -rel_op_condition_t ast_rel_op_condition(expr_t expr1, token_t rel_op, - expr_t expr2) -{ - rel_op_condition_t ret; - ret.file_loc = expr1.file_loc; - ret.type_tag = rel_op_condition_ast; - ret.expr1 = expr1; - ret.rel_op = rel_op; - ret.expr2 = expr2; - return ret; -} - -// Return an AST for an odd condition -condition_t ast_condition_db(db_condition_t db_cond) -{ - condition_t ret; - ret.file_loc = db_cond.file_loc; - ret.type_tag = db_condition_ast; - ret.cond_kind = ck_db; - ret.data.db_cond = db_cond; - return ret; -} - -// Return an AST for a relational condition -condition_t ast_condition_rel_op(rel_op_condition_t rel_op_cond) -{ - condition_t ret; - ret.file_loc = rel_op_cond.file_loc; - ret.type_tag = condition_ast; - ret.cond_kind = ck_rel; - ret.data.rel_op_cond = rel_op_cond; - return ret; -} - -// Return an AST for an odd condition -binary_op_expr_t ast_binary_op_expr(expr_t expr1, token_t arith_op, - expr_t expr2) -{ - binary_op_expr_t ret; - ret.file_loc = expr1.file_loc; - ret.type_tag = binary_op_expr_ast; - - expr_t *p = (expr_t *) malloc(sizeof(expr_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "expr_t"); - } - *p = expr1; - ret.expr1 = p; - - ret.arith_op = arith_op; - - p = (expr_t *) malloc(sizeof(expr_t)); - if (p == NULL) { - bail_with_error("Unable to allocate space for a %s!", "expr_t"); - } - *p = expr2; - ret.expr2 = p; - - return ret; -} - -// Return an expression AST for a binary operation expresion -expr_t ast_expr_binary_op(binary_op_expr_t e) -{ - expr_t ret; - ret.file_loc = e.file_loc; - ret.type_tag = expr_ast; - ret.expr_kind = expr_bin; - ret.data.binary = e; - return ret; -} - -// Return an expression AST for a signed expression -expr_t ast_expr_signed_expr(token_t sign, expr_t e) -{ - expr_t ret; - ret.file_loc = file_location_copy(sign.file_loc); - ret.type_tag = expr_ast; - switch (sign.code) { - case minussym: - ret.expr_kind = expr_negated; - negated_expr_t ne; - ne.file_loc = ret.file_loc; - ne.type_tag = negated_expr_ast; - ne.expr = (expr_t *)ast_heap_copy((AST)e); - ret.data.negated = ne; - break; - case plussym: - // don't make any changes, use e as the result - return e; - break; - default: - bail_with_error("Unexpected sign token in ast_expr_signed_expr: %d", - sign.code); - break; - } - return ret; -} - -// Return an expression AST for an signed number -expr_t ast_expr_pos_number(token_t sign, number_t number) -{ - expr_t ret; - ret.file_loc = file_location_copy(sign.file_loc); - ret.type_tag = expr_ast; - ret.expr_kind = expr_number; - ret.data.number = number; - return ret; -} - -// Return an AST for the given token -token_t ast_token(file_location *file_loc, const char *text, int code) -{ - token_t ret; - ret.file_loc = file_loc; - ret.type_tag = token_ast; - ret.text = text; - ret.code = code; - return ret; -} - -// Return an AST for a (signed) number with the given value -number_t ast_number(token_t sgn, word_type value) -{ - number_t ret; - ret.file_loc = file_location_copy(sgn.file_loc); - ret.type_tag = number_ast; - ret.value = value; - return ret; -} - -// Return an AST for an identifier -ident_t ast_ident(file_location *file_loc, const char *name) -{ - ident_t ret; - ret.file_loc = file_loc; - ret.type_tag = ident_ast; - ret.name = name; - return ret; -} - -// Return an AST for an expression that's a binary expression -expr_t ast_expr_binary_op_expr(binary_op_expr_t e) -{ - expr_t ret; - ret.file_loc = e.file_loc; - ret.type_tag = binary_op_expr_ast; - ret.expr_kind = expr_bin; - ret.data.binary = e; - return ret; -} - -// Return an AST for an expression that's an identifier -expr_t ast_expr_ident(ident_t e) -{ - expr_t ret; - ret.file_loc = e.file_loc; - ret.type_tag = expr_ast; - ret.expr_kind = expr_ident; - ret.data.ident = e; - return ret; -} - -// Return an AST for an expression that's a number -expr_t ast_expr_number(number_t e) -{ - expr_t ret; - ret.file_loc = e.file_loc; - ret.type_tag = expr_ast; - ret.expr_kind = expr_number; - ret.data.number = e; - return ret; -} - -// Requires: lst is a pointer to a non-circular -// linked list with next pointers -// as in generic_t -// Return a pointer to the last element in lst. -// This only returns NULL if lst == NULL. -void *ast_last_list_elem(void *lst) -{ - // debug_print("Entering ast_last_list_elem\n"); - if (lst == NULL) { - return lst; - } - // assert(lst != NULL); - void *prev = NULL; - while (lst != NULL) { - prev = lst; - lst = ((generic_t *)lst)->next; - } - // here lst == NULL; - return prev; -} - -// Requires: lst is a pointer to a non-circular -// linked list with next pointers -// as in generic_t -// Return the number of elements in the linked list lst -int ast_list_length(void *lst) -{ - int ret = 0; - generic_t *p = (generic_t *) lst; - while (p != NULL) { - p = p->next; - ret++; - } - return ret; -} - -// Requires: lst is a pointer to a non-circular -// linked list with next pointers -// as in generic_t -// Is lst empty? -bool ast_list_is_empty(void *lst) -{ - return lst == NULL; -} +/* $Id: ast.c,v 1.15 2024/11/03 22:49:33 leavens Exp $ */ +#include +#include +#include +#include "utilities.h" +#include "ast.h" +#include "spl.tab.h" + +// Return the file location from an AST +file_location *ast_file_loc(AST t) { + return t.generic.file_loc; +} + +// Return the filename from the AST t +const char *ast_filename(AST t) { + return ast_file_loc(t)->filename; +} + +// Return the line number from the AST t +unsigned int ast_line(AST t) { + return ast_file_loc(t)->line; +} + +// Return the type tag of the AST t +AST_type ast_type_tag(AST t) { + return t.generic.type_tag; +} + +// Return a pointer to a fresh copy of t +// that has been allocated on the heap +AST *ast_heap_copy(AST t) { + AST *ret = (AST *)malloc(sizeof(AST)); + if (ret == NULL) { + bail_with_error("Cannot allocate an AST heap copy!"); + } + *ret = t; + return ret; +} + +// Return an AST for a block which contains the given ASTs. +block_t ast_block(token_t begin_tok, const_decls_t const_decls, + var_decls_t var_decls, proc_decls_t proc_decls, + stmts_t stmts) +{ + block_t ret; + ret.file_loc = file_location_copy(begin_tok.file_loc); + ret.type_tag = block_ast; + ret.const_decls = const_decls; + ret.var_decls = var_decls; + ret.proc_decls = proc_decls; + ret.stmts = stmts; + return ret; +} + +// Return an AST for an empty const decls +extern const_decls_t ast_const_decls_empty(empty_t empty) +{ + const_decls_t ret; + ret.file_loc = empty.file_loc; + ret.type_tag = const_decls_ast; + ret.start = NULL; + return ret; +} + +// Return an AST for the const decls +const_decls_t ast_const_decls(const_decls_t const_decls, + const_decl_t const_decl) +{ + const_decls_t ret = const_decls; + // make a copy of const_decl on the heap + const_decl_t *p = (const_decl_t *) malloc(sizeof(const_decl_t)); + if (p == NULL) { + bail_with_error("Cannot allocate space for %s!", "const_decl_t"); + } + *p = const_decl; + p->next = NULL; + const_decl_t *last = ast_last_list_elem(ret.start); + if (last == NULL) { + ret.start = p; + } else { + last->next = p; + } + return ret; +} + + + +// Return an AST for a const_decl +const_decl_t ast_const_decl(const_def_list_t const_def_list) +{ + const_decl_t ret; + ret.file_loc = const_def_list.file_loc; + ret.type_tag = const_decl_ast; + ret.const_def_list = const_def_list; + ret.next = NULL; + return ret; +} + +// Return an AST for const-def-list that is a singleton +extern const_def_list_t ast_const_def_list_singleton(const_def_t const_def) +{ + const_def_list_t ret; + ret.file_loc = const_def.file_loc; + ret.type_tag = const_def_list_ast; + const_def_t *p = (const_def_t *) malloc(sizeof(const_def_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "const_def_t"); + } + *p = const_def; + p->next = NULL; + ret.start = p; + return ret; +} + +// Return an AST for const_defs +extern const_def_list_t ast_const_def_list(const_def_list_t const_def_list, + const_def_t const_def) +{ + const_def_list_t ret = const_def_list; + // make a copy of const_def on the heap + const_def_t *p = (const_def_t *) malloc(sizeof(const_def_t)); + if (p == NULL) { + bail_with_error("Cannot allocate space for %s!", "const_def_t"); + } + *p = const_def; + p->next = NULL; + const_def_t *last = ast_last_list_elem(ret.start); + if (last == NULL) { + ret.start = p; + } else { + last->next = p; + } + return ret; +} + +// Return an AST for a const-def +const_def_t ast_const_def(ident_t ident, number_t number) +{ + const_def_t ret; + ret.file_loc = file_location_copy(ident.file_loc); + assert((ret.file_loc)->filename != NULL); + ret.type_tag = const_def_ast; + ret.next = NULL; + ret.ident = ident; + ret.number = number; + return ret; +} + + +// Return an AST for varDecls that are empty +var_decls_t ast_var_decls_empty(empty_t empty) +{ + var_decls_t ret; + ret.file_loc = empty.file_loc; + ret.type_tag = var_decls_ast; + ret.var_decls = NULL; + return ret; +} + +// Return an AST varDecls that have some var_decls +var_decls_t ast_var_decls(var_decls_t var_decls, var_decl_t var_decl) +{ + var_decls_t ret = var_decls; + // make a copy of var_decl on the heap + var_decl_t *p = (var_decl_t *) malloc(sizeof(var_decl_t)); + if (p == NULL) { + bail_with_error("Cannot allocate space for %s!", "var_decl_t"); + } + *p = var_decl; + p->next = NULL; + var_decl_t *last = ast_last_list_elem(ret.var_decls); + if (last == NULL) { + ret.var_decls = p; + } else { + last->next = p; + } + return ret; +} + +// Return an AST for a var_decl +var_decl_t ast_var_decl(ident_list_t ident_list) +{ + var_decl_t ret; + ret.file_loc = ident_list.file_loc; + ret.type_tag = var_decl_ast; + ret.next = NULL; + ret.ident_list = ident_list; + return ret; +} + +// Return an AST made for one ident +extern ident_list_t ast_ident_list_singleton(ident_t ident) +{ + ident_list_t ret; + ret.file_loc = ident.file_loc; + ret.type_tag = ident_list_ast; + // make a copy of ident on the heap + ident_t *p = (ident_t *) malloc(sizeof(ident_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "ident_t"); + } + *p = ident; + p->next = NULL; + ret.start = p; + return ret; +} + +// Return an AST made for idents +extern ident_list_t ast_ident_list(ident_list_t ident_list, ident_t ident) +{ + ident_list_t ret = ident_list; + // make a copy of ident on the heap + ident_t *p = (ident_t *) malloc(sizeof(ident_t)); + if (p == NULL) { + bail_with_error("Cannot allocate space for %s!", "ident_t"); + } + *p = ident; + p->next = NULL; + ident_t *last = ast_last_list_elem(ret.start); + if (last == NULL) { + ret.start = p; + } else { + last->next = p; + } + return ret; +} + +// Return an AST for proc_decls +proc_decls_t ast_proc_decls_empty(empty_t empty) +{ + proc_decls_t ret; + ret.file_loc = empty.file_loc; + ret.type_tag = proc_decls_ast; + ret.proc_decls = NULL; + return ret; +} + +// Return an AST for proc_decls +proc_decls_t ast_proc_decls(proc_decls_t proc_decls, + proc_decl_t proc_decl) +{ + proc_decls_t ret = proc_decls; + // make a copy of proc_decl on the heap + proc_decl_t *p = (proc_decl_t *) malloc(sizeof(proc_decl_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "proc_decl_t"); + } + *p = proc_decl; + p->next = NULL; + proc_decl_t *last = ast_last_list_elem(ret.proc_decls); + if (last == NULL) { + ret.proc_decls = p; + } else { + last->next = p; + } + return ret; +} + +// Return an AST for a proc_decl +proc_decl_t ast_proc_decl(ident_t ident, block_t block) +{ + proc_decl_t ret; + ret.file_loc = file_location_copy(ident.file_loc); + ret.type_tag = proc_decl_ast; + ret.next = NULL; + ret.name = ident.name; + block_t *p = (block_t *) malloc(sizeof(block_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "block_t"); + } + *p = block; + ret.block = p; + return ret; +} + +// Return an AST for a print statement +print_stmt_t ast_print_stmt(expr_t expr) { + print_stmt_t ret; + ret.file_loc = expr.file_loc; + ret.type_tag = print_stmt_ast; + ret.expr = expr; + return ret; +} + +// Return an AST for a read statement +read_stmt_t ast_read_stmt(ident_t ident) { + read_stmt_t ret; + ret.file_loc = file_location_copy(ident.file_loc); + ret.type_tag = read_stmt_ast; + ret.name = ident.name; + return ret; +} + +// Return an immediate data holding an address +while_stmt_t ast_while_stmt(condition_t condition, stmts_t body) { + while_stmt_t ret; + ret.file_loc = condition.file_loc; + ret.type_tag = while_stmt_ast; + ret.condition = condition; + stmts_t *p = (stmts_t *) malloc(sizeof(stmts_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "stmts_t"); + } + *p = body; + ret.body = p; + return ret; +} + +// Return an AST for an if-then-else statement +if_stmt_t ast_if_then_else_stmt(condition_t condition, + stmts_t then_stmts, stmts_t else_stmts) +{ + if_stmt_t ret; + ret.file_loc = condition.file_loc; + ret.type_tag = if_stmt_ast; + ret.condition = condition; + // copy then_stmt to the heap + stmts_t *p = (stmts_t *) malloc(sizeof(stmts_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "stmts_t"); + } + *p = then_stmts; + ret.then_stmts = p; + // copy else_stmts to the heap + p = (stmts_t *) malloc(sizeof(stmts_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "stmts_t"); + } + *p = else_stmts; + ret.else_stmts = p; + return ret; +} + +// Return an AST for a (short) if-then statement +// Note that the else part is a NULL pointer +extern if_stmt_t ast_if_then_stmt(condition_t condition, + stmts_t then_stmts) +{ + if_stmt_t ret; + ret.file_loc = condition.file_loc; + ret.type_tag = if_stmt_ast; + ret.condition = condition; + // copy then_stmt to the heap + stmts_t *p = (stmts_t *) malloc(sizeof(stmts_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "stmts_t"); + } + *p = then_stmts; + ret.then_stmts = p; + ret.else_stmts = NULL; + return ret; +} + +// Return an AST for a begin statement +// containing the given list of statements +block_stmt_t ast_block_stmt(block_t block) +{ + block_stmt_t ret; + ret.file_loc = block.file_loc; + ret.type_tag = block_stmt_ast; + // copy the block to the heap + block_t *p = (block_t *) malloc(sizeof(block_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "block_t"); + } + *p = block; + ret.block = p; + return ret; +} + +// Return an AST for a call statment + call_stmt_t ast_call_stmt(ident_t ident) +{ + call_stmt_t ret; + ret.file_loc = file_location_copy(ident.file_loc); + ret.type_tag = call_stmt_ast; + ret.name = ident.name; + return ret; +} + +// Return an AST for an assignment statement +assign_stmt_t ast_assign_stmt(ident_t ident, expr_t expr) +{ + assign_stmt_t ret; + ret.file_loc = file_location_copy(ident.file_loc); + ret.type_tag = assign_stmt_ast; + ret.name = ident.name; + assert(ret.name != NULL); + expr_t *p = (expr_t *) malloc(sizeof(expr_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "expr_t"); + } + *p = expr; + ret.expr = p; + assert(ret.expr != NULL); + return ret; +} + +// Return an AST for the list of statements +stmts_t ast_stmts_empty(empty_t empty) +{ + stmts_t ret; + ret.file_loc = file_location_copy(empty.file_loc); + ret.type_tag = stmts_ast; + ret.stmts_kind = empty_stmts_e; + return ret; +} + +// Return an AST for empty found in the given file location +empty_t ast_empty(file_location *file_loc) +{ + empty_t ret; + ret.file_loc = file_loc; + ret.type_tag = empty_ast; + return ret; +} + +// Return an AST for the list of statements +stmts_t ast_stmts(stmt_list_t stmt_list) +{ + stmts_t ret; + ret.file_loc = stmt_list.file_loc; + ret.type_tag = stmts_ast; + ret.stmts_kind = stmt_list_e; + ret.stmt_list = stmt_list; + return ret; +} + + +// Return an AST for the list of statements +stmt_list_t ast_stmt_list_singleton(stmt_t stmt) { + // debug_print("Entering ast_stmts_singleton\n"); + stmt_list_t ret; + ret.file_loc = stmt.file_loc; + ret.type_tag = stmt_list_ast; + stmt.next = NULL; + // copy stmt to the heap + stmt_t *p = (stmt_t *) malloc(sizeof(stmt_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "stmt_t"); + } + *p = stmt; + p->next = NULL; + // there will be no statments after stmt in the list + ret.start = p; + return ret; +} + +// Return an AST for the list of statements +extern stmt_list_t ast_stmt_list(stmt_list_t stmt_list, stmt_t stmt) { + // debug_print("Entering ast_stmt_list...\n"); + stmt_list_t ret = stmt_list; + // copy stmt to the heap + stmt_t *s = (stmt_t *) malloc(sizeof(stmt_t)); + if (s == NULL) { + bail_with_error("Cannot allocate space for %s!", "stmt_t"); + } + *s = stmt; + s->next = NULL; + stmt_t *last = ast_last_list_elem(ret.start); + assert(last != NULL); // because there are no empty lists of stmts + last->next = s; + return ret; +} + +// Return an AST for the given statment +stmt_t ast_stmt_assign(assign_stmt_t s) +{ + stmt_t ret; + ret.file_loc = s.file_loc; + ret.type_tag = stmt_ast; + ret.next = NULL; + ret.stmt_kind = assign_stmt; + ret.data.assign_stmt = s; + return ret; +} + +// Return an AST for the given statment +stmt_t ast_stmt_call(call_stmt_t s) +{ + stmt_t ret; + ret.file_loc = s.file_loc; + ret.type_tag = stmt_ast; + ret.next = NULL; + ret.stmt_kind = call_stmt; + ret.data.call_stmt = s; + return ret; +} + +// Return an AST for the given statment +stmt_t ast_stmt_block(block_stmt_t s) +{ + stmt_t ret; + ret.file_loc = s.file_loc; + ret.type_tag = stmt_ast; + ret.next = NULL; + ret.stmt_kind = block_stmt; + ret.data.block_stmt = s; + return ret; +} + +// Return an AST for the given statment +stmt_t ast_stmt_if(if_stmt_t s) +{ + stmt_t ret; + ret.file_loc = s.file_loc; + ret.type_tag = stmt_ast; + ret.next = NULL; + ret.stmt_kind = if_stmt; + ret.data.if_stmt = s; + return ret; +} + +// Return an AST for the given statment +stmt_t ast_stmt_while(while_stmt_t s) +{ + stmt_t ret; + ret.file_loc = s.file_loc; + ret.type_tag = stmt_ast; + ret.next = NULL; + ret.stmt_kind = while_stmt; + ret.data.while_stmt = s; + return ret; +} + +// Return an AST for the given statment +stmt_t ast_stmt_read(read_stmt_t s) +{ + stmt_t ret; + ret.file_loc = s.file_loc; + ret.type_tag = stmt_ast; + ret.next = NULL; + ret.stmt_kind = read_stmt; + ret.data.read_stmt = s; + return ret; +} + +// Return an AST for the given statment +stmt_t ast_stmt_print(print_stmt_t s) +{ + // debug_print("Entering ast_stmt_print...\n"); + stmt_t ret; + ret.file_loc = s.file_loc; + ret.type_tag = stmt_ast; + ret.next = NULL; + ret.stmt_kind = print_stmt; + ret.data.print_stmt = s; + return ret; +} + +// Return an AST for an odd condition +db_condition_t ast_db_condition(expr_t dividend, expr_t divisor) +{ + db_condition_t ret; + ret.file_loc = dividend.file_loc; + ret.type_tag = db_condition_ast; + ret.dividend = dividend; + ret.divisor = divisor; + return ret; +} + +// Return an AST for an initializer with the given value +rel_op_condition_t ast_rel_op_condition(expr_t expr1, token_t rel_op, + expr_t expr2) +{ + rel_op_condition_t ret; + ret.file_loc = expr1.file_loc; + ret.type_tag = rel_op_condition_ast; + ret.expr1 = expr1; + ret.rel_op = rel_op; + ret.expr2 = expr2; + return ret; +} + +// Return an AST for an odd condition +condition_t ast_condition_db(db_condition_t db_cond) +{ + condition_t ret; + ret.file_loc = db_cond.file_loc; + ret.type_tag = db_condition_ast; + ret.cond_kind = ck_db; + ret.data.db_cond = db_cond; + return ret; +} + +// Return an AST for a relational condition +condition_t ast_condition_rel_op(rel_op_condition_t rel_op_cond) +{ + condition_t ret; + ret.file_loc = rel_op_cond.file_loc; + ret.type_tag = condition_ast; + ret.cond_kind = ck_rel; + ret.data.rel_op_cond = rel_op_cond; + return ret; +} + +// Return an AST for an odd condition +binary_op_expr_t ast_binary_op_expr(expr_t expr1, token_t arith_op, + expr_t expr2) +{ + binary_op_expr_t ret; + ret.file_loc = expr1.file_loc; + ret.type_tag = binary_op_expr_ast; + + expr_t *p = (expr_t *) malloc(sizeof(expr_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "expr_t"); + } + *p = expr1; + ret.expr1 = p; + + ret.arith_op = arith_op; + + p = (expr_t *) malloc(sizeof(expr_t)); + if (p == NULL) { + bail_with_error("Unable to allocate space for a %s!", "expr_t"); + } + *p = expr2; + ret.expr2 = p; + + return ret; +} + +// Return an expression AST for a binary operation expresion +expr_t ast_expr_binary_op(binary_op_expr_t e) +{ + expr_t ret; + ret.file_loc = e.file_loc; + ret.type_tag = expr_ast; + ret.expr_kind = expr_bin; + ret.data.binary = e; + return ret; +} + +// Return an expression AST for a signed expression +expr_t ast_expr_signed_expr(token_t sign, expr_t e) +{ + expr_t ret; + ret.file_loc = file_location_copy(sign.file_loc); + ret.type_tag = expr_ast; + switch (sign.code) { + case minussym: + ret.expr_kind = expr_negated; + negated_expr_t ne; + ne.file_loc = ret.file_loc; + ne.type_tag = negated_expr_ast; + ne.expr = (expr_t *)ast_heap_copy((AST)e); + ret.data.negated = ne; + break; + case plussym: + // don't make any changes, use e as the result + return e; + break; + default: + bail_with_error("Unexpected sign token in ast_expr_signed_expr: %d", + sign.code); + break; + } + return ret; +} + +// Return an expression AST for an signed number +expr_t ast_expr_pos_number(token_t sign, number_t number) +{ + expr_t ret; + ret.file_loc = file_location_copy(sign.file_loc); + ret.type_tag = expr_ast; + ret.expr_kind = expr_number; + ret.data.number = number; + return ret; +} + +// Return an AST for the given token +token_t ast_token(file_location *file_loc, const char *text, int code) +{ + token_t ret; + ret.file_loc = file_loc; + ret.type_tag = token_ast; + ret.text = text; + ret.code = code; + return ret; +} + +// Return an AST for a (signed) number with the given value +number_t ast_number(token_t sgn, word_type value) +{ + number_t ret; + ret.file_loc = file_location_copy(sgn.file_loc); + ret.type_tag = number_ast; + ret.value = value; + return ret; +} + +// Return an AST for an identifier +ident_t ast_ident(file_location *file_loc, const char *name) +{ + ident_t ret; + ret.file_loc = file_loc; + ret.type_tag = ident_ast; + ret.name = name; + return ret; +} + +// Return an AST for an expression that's a binary expression +expr_t ast_expr_binary_op_expr(binary_op_expr_t e) +{ + expr_t ret; + ret.file_loc = e.file_loc; + ret.type_tag = binary_op_expr_ast; + ret.expr_kind = expr_bin; + ret.data.binary = e; + return ret; +} + +// Return an AST for an expression that's an identifier +expr_t ast_expr_ident(ident_t e) +{ + expr_t ret; + ret.file_loc = e.file_loc; + ret.type_tag = expr_ast; + ret.expr_kind = expr_ident; + ret.data.ident = e; + return ret; +} + +// Return an AST for an expression that's a number +expr_t ast_expr_number(number_t e) +{ + expr_t ret; + ret.file_loc = e.file_loc; + ret.type_tag = expr_ast; + ret.expr_kind = expr_number; + ret.data.number = e; + return ret; +} + +// Requires: lst is a pointer to a non-circular +// linked list with next pointers +// as in generic_t +// Return a pointer to the last element in lst. +// This only returns NULL if lst == NULL. +void *ast_last_list_elem(void *lst) +{ + // debug_print("Entering ast_last_list_elem\n"); + if (lst == NULL) { + return lst; + } + // assert(lst != NULL); + void *prev = NULL; + while (lst != NULL) { + prev = lst; + lst = ((generic_t *)lst)->next; + } + // here lst == NULL; + return prev; +} + +// Requires: lst is a pointer to a non-circular +// linked list with next pointers +// as in generic_t +// Return the number of elements in the linked list lst +int ast_list_length(void *lst) +{ + int ret = 0; + generic_t *p = (generic_t *) lst; + while (p != NULL) { + p = p->next; + ret++; + } + return ret; +} + +// Requires: lst is a pointer to a non-circular +// linked list with next pointers +// as in generic_t +// Is lst empty? +bool ast_list_is_empty(void *lst) +{ + return lst == NULL; +} diff --git a/ast.h b/FromGithub/ast.h old mode 100755 new mode 100644 similarity index 96% rename from ast.h rename to FromGithub/ast.h index ab3f532..ac0deba --- a/ast.h +++ b/FromGithub/ast.h @@ -1,537 +1,537 @@ -/* $Id: ast.h,v 1.18 2024/11/03 22:49:33 leavens Exp $ */ -#ifndef _AST_H -#define _AST_H -#include -#include "machine_types.h" -#include "file_location.h" -#include "id_use.h" - -// types of ASTs (type tags) -typedef enum { - block_ast, const_decls_ast, const_decl_ast, - const_def_list_ast, const_def_ast, - var_decls_ast, var_decl_ast, ident_list_ast, - proc_decls_ast, proc_decl_ast, - stmts_ast, empty_ast, stmt_list_ast, stmt_ast, - assign_stmt_ast, call_stmt_ast, if_stmt_ast, while_stmt_ast, - read_stmt_ast, print_stmt_ast, block_stmt_ast, - condition_ast, db_condition_ast, rel_op_condition_ast, - expr_ast, binary_op_expr_ast, negated_expr_ast, ident_ast, number_ast, - token_ast -} AST_type; - -// The following types for structs named N_t -// are returned by the parser. -// The struct N_t is the type of information kept in the AST -// that is related to the nonterminal N in the abstract syntax. - -// The generic struct type (generic_t) has the fields that -// should be in all alternatives for ASTs. -typedef struct { - file_location *file_loc; - AST_type type_tag; // says what field of the union is active - void *next; // for lists -} generic_t; - -// empty ::= -typedef struct { - file_location *file_loc; - AST_type type_tag; -} empty_t; - -// identifiers -typedef struct ident_s { - file_location *file_loc; - AST_type type_tag; - struct ident_s *next; // for lists this is a part of - const char *name; - id_use *idu; -} ident_t; - -// (possibly signed) numbers -typedef struct { - file_location *file_loc; - AST_type type_tag; - const char *text; - word_type value; -} number_t; - -// tokens as ASTs -typedef struct { - file_location *file_loc; - AST_type type_tag; - const char *text; - int code; -} token_t; - -// kinds of expressions -typedef enum { expr_bin, expr_negated, expr_ident, expr_number } expr_kind_e; - -// forward declaration for the expr type -struct expr_s; - -// expr ::= expr arithOp expr -// arithOp ::= + | - | * | / -typedef struct { - file_location *file_loc; - AST_type type_tag; - struct expr_s *expr1; - token_t arith_op; - struct expr_s *expr2; -} binary_op_expr_t; - -// expr ::= - expr -typedef struct { - file_location *file_loc; - AST_type type_tag; - struct expr_s *expr; -} negated_expr_t; - -// expr ::= expr arithOp expr | ident | number -typedef struct expr_s { - file_location *file_loc; - AST_type type_tag; - expr_kind_e expr_kind; - union { - binary_op_expr_t binary; - negated_expr_t negated; - ident_t ident; - number_t number; - } data; -} expr_t; - -// kinds of conditions -typedef enum { ck_db, ck_rel } condition_kind_e; - -typedef struct { - file_location *file_loc; - AST_type type_tag; - expr_t dividend; - expr_t divisor; -} db_condition_t; - -typedef struct { - file_location *file_loc; - AST_type type_tag; - expr_t expr1; - token_t rel_op; - expr_t expr2; -} rel_op_condition_t; - -// condition ::= divisible expr expr | expr relOp expr -typedef struct { - file_location *file_loc; - AST_type type_tag; - condition_kind_e cond_kind; - union cond_u { - db_condition_t db_cond; - rel_op_condition_t rel_op_cond; - } data; -} condition_t; - -// kinds of statements -typedef enum { assign_stmt, call_stmt, if_stmt, while_stmt, - read_stmt, print_stmt, block_stmt } stmt_kind_e; - -// forward declaration of statement type -struct stmt_s; - -// stmt-list ::= stmt | stmt-list stmt -typedef struct { - file_location *file_loc; - AST_type type_tag; - struct stmt_s *start; -} stmt_list_t; - -typedef enum { empty_stmts_e, stmt_list_e } stmts_kind_e; - -// stmts ::= { stmts } -typedef struct { - file_location *file_loc; - AST_type type_tag; - stmts_kind_e stmts_kind; - stmt_list_t stmt_list; // when stmts_kind != empty_stmts_e -} stmts_t; - -// stmt ::= ident := expr -typedef struct { - file_location *file_loc; - AST_type type_tag; - const char *name; - struct expr_s *expr; - id_use *idu; -} assign_stmt_t; - -// stmt ::= call ident -typedef struct { - file_location *file_loc; - AST_type type_tag; - const char *name; - id_use *idu; -} call_stmt_t; - -// forward declaration for block type -struct block_s; - -// block-stmt ::= block -typedef struct block_stmt_s { - file_location *file_loc; - AST_type type_tag; - struct block_s *block; -} block_stmt_t; - -// if-stmt ::= if condition stmts stmts | if condition stmts -typedef struct { - file_location *file_loc; - AST_type type_tag; - condition_t condition; - stmts_t *then_stmts; - stmts_t *else_stmts; -} if_stmt_t; - -// stmt ::= while condition stmt -typedef struct { - file_location *file_loc; - AST_type type_tag; - condition_t condition; - stmts_t *body; -} while_stmt_t; - -// stmt ::= read ident -typedef struct { - file_location *file_loc; - AST_type type_tag; - const char *name; - id_use *idu; -} read_stmt_t; - -// stmt ::= print expr -typedef struct { - file_location *file_loc; - AST_type type_tag; - expr_t expr; -} print_stmt_t; - -// stmt ::= assign-stmt | call-stmt | if-stmt -// | while-stmt | read-stmt | print-stmt | block-stmt -typedef struct stmt_s { - file_location *file_loc; - AST_type type_tag; - struct stmt_s *next; // for lists this is a part of - stmt_kind_e stmt_kind; - union { - assign_stmt_t assign_stmt; - call_stmt_t call_stmt; - if_stmt_t if_stmt; - while_stmt_t while_stmt; - read_stmt_t read_stmt; - print_stmt_t print_stmt; - block_stmt_t block_stmt; - } data; -} stmt_t; - -// procDecl ::= proc ident block -typedef struct proc_decl_s { - file_location *file_loc; - AST_type type_tag; - struct proc_decl_s *next; // for lists - const char *name; - struct block_s *block; -} proc_decl_t; - -// proc-decls ::= { proc-decl } -typedef struct { - file_location *file_loc; - AST_type type_tag; - proc_decl_t *proc_decls; -} proc_decls_t; - -// ident-list ::= ident | ident-list ident -typedef struct { - file_location *file_loc; - AST_type type_tag; - ident_t *start; -} ident_list_t; - -// var-decl ::= var ident-list -typedef struct var_decl_s { - file_location *file_loc; - AST_type type_tag; - struct var_decl_s *next; // for lists this is a part of - ident_list_t ident_list; -} var_decl_t; - -// var-decls ::= { var-decl } -typedef struct { - file_location *file_loc; - AST_type type_tag; - var_decl_t *var_decls; -} var_decls_t; - -// const-def ::= ident number -typedef struct const_def_s { - file_location *file_loc; - AST_type type_tag; - struct const_def_s *next; // for lists this is a part of - ident_t ident; - number_t number; -} const_def_t; - -// const-def-list ::= { const-def } -typedef struct { - file_location *file_loc; - AST_type type_tag; - const_def_t *start; -} const_def_list_t; - -// const-decl ::= const const-def-list -typedef struct const_decl_s { - file_location *file_loc; - AST_type type_tag; - struct const_decl_s *next; // for lists this is a part of - const_def_list_t const_def_list; -} const_decl_t; - -// const-decls ::= { const-decl } -typedef struct { - file_location *file_loc; - AST_type type_tag; - const_decl_t *start; -} const_decls_t; - -// block ::= begin const-decls var-decls proc-decls stmts -typedef struct block_s { - file_location *file_loc; - AST_type type_tag; - const_decls_t const_decls; - var_decls_t var_decls; - proc_decls_t proc_decls; - stmts_t stmts; -} block_t; - -// program ::= block - -// The AST definition used by bison -typedef union AST_u { - generic_t generic; - block_t block; - const_decls_t const_decls; - const_decl_t const_decl; - const_def_list_t const_def_list; - const_def_t const_def; - var_decls_t var_decls; - var_decl_t var_decl; - ident_list_t ident_list; - proc_decls_t proc_decls; - proc_decl_t proc_decl; - stmts_t stmts; - stmt_list_t stmt_list; - stmt_t stmt; - assign_stmt_t assign_stmt; - call_stmt_t call_stmt; - if_stmt_t if_stmt; - while_stmt_t while_stmt; - read_stmt_t read_stmt; - print_stmt_t print_stmt; - block_stmt_t block_stmt; - condition_t condition; - rel_op_condition_t rel_op_condition; - db_condition_t db_condition; - expr_t expr; - binary_op_expr_t binary_op_expr; - token_t token; - number_t number; - ident_t ident; - empty_t empty; -} AST; - -// Return the file location from an AST -extern file_location *ast_file_loc(AST t); - -// Return the filename from the AST t -extern const char *ast_filename(AST t); - -// Return the line number from the AST t -extern unsigned int ast_line(AST t); - -// Return the type tag of the AST t -extern AST_type ast_type_tag(AST t); - -// Return a pointer to a fresh copy of t -// that has been allocated on the heap -extern AST *ast_heap_copy(AST t); - -// Return an AST for a block which contains the given ASTs. -extern block_t ast_block(token_t begin_tok, const_decls_t const_decls, var_decls_t var_decls, proc_decls_t proc_decls, stmts_t stmts); - -// Return an AST for an empty const decls -extern const_decls_t ast_const_decls_empty(empty_t empty); - -// Return an AST for the const decls -extern const_decls_t ast_const_decls(const_decls_t const_decls, - const_decl_t const_decl); - -// Return an AST for a const_decl -extern const_decl_t ast_const_decl(const_def_list_t const_def_list); - -// Return an AST for const_def_list -extern const_def_list_t ast_const_def_list_singleton(const_def_t const_def); - -// Return an AST for adding to a const_def_list -extern const_def_list_t ast_const_def_list(const_def_list_t const_def_list, - const_def_t const_def); - -// Return an AST for a const-def -extern const_def_t ast_const_def(ident_t ident, number_t number); - -// Return an AST for varDecls that are empty -extern var_decls_t ast_var_decls_empty(empty_t empty); - -// Return an AST varDecls that have some var_decls -extern var_decls_t ast_var_decls(var_decls_t var_decls, var_decl_t var_decl); - -// Return an AST for a var_decl -extern var_decl_t ast_var_decl(ident_list_t ident_list); - -// Return an AST made for one ident -extern ident_list_t ast_ident_list_singleton(ident_t ident); - -// Return an AST made for ident lists -extern ident_list_t ast_ident_list(ident_list_t ident_list, ident_t ident); - -// Return an AST for proc_decls -extern proc_decls_t ast_proc_decls_empty(empty_t empty); - -// Return an AST for proc_decls -extern proc_decls_t ast_proc_decls(proc_decls_t proc_decls, - proc_decl_t proc_decl); - -// Return an AST for a proc_decl -extern proc_decl_t ast_proc_decl(ident_t ident, block_t block); - - -// Return an AST for the list of statements -extern stmts_t ast_stmts_empty(empty_t empty); - -// Return an AST for empty found in the given file location -extern empty_t ast_empty(file_location *file_loc); - -// Return an AST for the list of statements -extern stmts_t ast_stmts(stmt_list_t stmt_list); - -// Return an AST for a list of statements that has stmt as a member -extern stmt_list_t ast_stmt_list_singleton(stmt_t stmt); - -// Return an AST for the list of statements -extern stmt_list_t ast_stmt_list(stmt_list_t stmt_list, stmt_t stmt); - -// Return an AST for the given statement as a more general stmt AST -extern stmt_t ast_stmt_assign(assign_stmt_t s); - -// Return an AST for the given statement as a more general stmt AST -extern stmt_t ast_stmt_call(call_stmt_t s); - -// Return an AST for the given statement as a more general stmt AST -extern stmt_t ast_stmt_block(block_stmt_t s); - -// Return an AST for the given statement as a more general stmt AST -extern stmt_t ast_stmt_if(if_stmt_t s); - -// Return an AST for the given statement as a more general stmt AST -extern stmt_t ast_stmt_while(while_stmt_t s); - -// Return an AST for the given statement as a more general stmt AST -extern stmt_t ast_stmt_read(read_stmt_t s); - -// Return an AST for the given statement as a more general stmt AST -extern stmt_t ast_stmt_print(print_stmt_t s); - -// Return an AST for an assignment statement -extern assign_stmt_t ast_assign_stmt(ident_t ident, expr_t expr); - -// Return an AST for a call statement -extern call_stmt_t ast_call_stmt(ident_t ident); - -// Return an AST for an if-then-else statement -extern if_stmt_t ast_if_then_else_stmt(condition_t condition, - stmts_t then_stmts, stmts_t else_stmts); - -// Return an AST for a (short) if-then statement -// Note that the else part is a NULL pointer -extern if_stmt_t ast_if_then_stmt(condition_t condition, - stmts_t then_stmts); - -// Return an AST for a while statement -extern while_stmt_t ast_while_stmt(condition_t condition, stmts_t body); - -// Return an AST for a read statement -extern read_stmt_t ast_read_stmt(ident_t ident); - -// Return an AST for a print statement -extern print_stmt_t ast_print_stmt(expr_t expr); - -// Return an AST for a block statement -extern block_stmt_t ast_block_stmt(block_t block); - - -// Return an AST for an odd condition -extern db_condition_t ast_db_condition(expr_t dividend, expr_t divisor); - -// Return an AST for an initializer with the given value -extern rel_op_condition_t ast_rel_op_condition(expr_t expr1, token_t rel_op, - expr_t expr2); - -// Return an AST for an odd condition -extern condition_t ast_condition_db(db_condition_t db_cond); - -// Return an AST for a relational condition -extern condition_t ast_condition_rel_op(rel_op_condition_t rel_op_cond); - - -// Return an expression AST for a binary operation expresion -extern expr_t ast_expr_binary_op(binary_op_expr_t e1); - -// Return an expression AST for an identifier -extern expr_t ast_expr_ident(ident_t e); - -// Return an AST for an expression that's a number -extern expr_t ast_expr_number(number_t e); - -// Return an AST for a binary op expression -extern binary_op_expr_t ast_binary_op_expr(expr_t expr1, token_t arith_op, - expr_t expr2); - -// Return an expression AST for a signed expression -extern expr_t ast_expr_signed_expr(token_t sign, expr_t expr); - -// The following are made by the lexer... - -// Return an AST for the given token -extern token_t ast_token(file_location *file_loc, const char *text, int code); - -// Return an AST for an identifier -// found in the file named fn, on line ln, with the given name. -extern ident_t ast_ident(file_location *file_loc, const char *name); - -// Some operations on AST lists - -// Requires: lst is a pointer to a non-circular -// linked list with next pointers -// as in generic_t -// Return a pointer to the last element in lst. -// This only returns NULL if lst == NULL. -extern void *ast_last_list_elem(void *lst); - -// Requires: lst is a pointer to a non-circular -// linked list with next pointers -// as in generic_t -// Return the number of elements in the linked list lst -extern int ast_list_length(void *lst); - -// Requires: lst is a pointer to a non-circular -// linked list with next pointers -// as in generic_t -// Is lst empty? -extern bool ast_list_is_empty(void *lst); - -#endif +/* $Id: ast.h,v 1.18 2024/11/03 22:49:33 leavens Exp $ */ +#ifndef _AST_H +#define _AST_H +#include +#include "machine_types.h" +#include "file_location.h" +#include "id_use.h" + +// types of ASTs (type tags) +typedef enum { + block_ast, const_decls_ast, const_decl_ast, + const_def_list_ast, const_def_ast, + var_decls_ast, var_decl_ast, ident_list_ast, + proc_decls_ast, proc_decl_ast, + stmts_ast, empty_ast, stmt_list_ast, stmt_ast, + assign_stmt_ast, call_stmt_ast, if_stmt_ast, while_stmt_ast, + read_stmt_ast, print_stmt_ast, block_stmt_ast, + condition_ast, db_condition_ast, rel_op_condition_ast, + expr_ast, binary_op_expr_ast, negated_expr_ast, ident_ast, number_ast, + token_ast +} AST_type; + +// The following types for structs named N_t +// are returned by the parser. +// The struct N_t is the type of information kept in the AST +// that is related to the nonterminal N in the abstract syntax. + +// The generic struct type (generic_t) has the fields that +// should be in all alternatives for ASTs. +typedef struct { + file_location *file_loc; + AST_type type_tag; // says what field of the union is active + void *next; // for lists +} generic_t; + +// empty ::= +typedef struct { + file_location *file_loc; + AST_type type_tag; +} empty_t; + +// identifiers +typedef struct ident_s { + file_location *file_loc; + AST_type type_tag; + struct ident_s *next; // for lists this is a part of + const char *name; + id_use *idu; +} ident_t; + +// (possibly signed) numbers +typedef struct { + file_location *file_loc; + AST_type type_tag; + const char *text; + word_type value; +} number_t; + +// tokens as ASTs +typedef struct { + file_location *file_loc; + AST_type type_tag; + const char *text; + int code; +} token_t; + +// kinds of expressions +typedef enum { expr_bin, expr_negated, expr_ident, expr_number } expr_kind_e; + +// forward declaration for the expr type +struct expr_s; + +// expr ::= expr arithOp expr +// arithOp ::= + | - | * | / +typedef struct { + file_location *file_loc; + AST_type type_tag; + struct expr_s *expr1; + token_t arith_op; + struct expr_s *expr2; +} binary_op_expr_t; + +// expr ::= - expr +typedef struct { + file_location *file_loc; + AST_type type_tag; + struct expr_s *expr; +} negated_expr_t; + +// expr ::= expr arithOp expr | ident | number +typedef struct expr_s { + file_location *file_loc; + AST_type type_tag; + expr_kind_e expr_kind; + union { + binary_op_expr_t binary; + negated_expr_t negated; + ident_t ident; + number_t number; + } data; +} expr_t; + +// kinds of conditions +typedef enum { ck_db, ck_rel } condition_kind_e; + +typedef struct { + file_location *file_loc; + AST_type type_tag; + expr_t dividend; + expr_t divisor; +} db_condition_t; + +typedef struct { + file_location *file_loc; + AST_type type_tag; + expr_t expr1; + token_t rel_op; + expr_t expr2; +} rel_op_condition_t; + +// condition ::= divisible expr expr | expr relOp expr +typedef struct { + file_location *file_loc; + AST_type type_tag; + condition_kind_e cond_kind; + union cond_u { + db_condition_t db_cond; + rel_op_condition_t rel_op_cond; + } data; +} condition_t; + +// kinds of statements +typedef enum { assign_stmt, call_stmt, if_stmt, while_stmt, + read_stmt, print_stmt, block_stmt } stmt_kind_e; + +// forward declaration of statement type +struct stmt_s; + +// stmt-list ::= stmt | stmt-list stmt +typedef struct { + file_location *file_loc; + AST_type type_tag; + struct stmt_s *start; +} stmt_list_t; + +typedef enum { empty_stmts_e, stmt_list_e } stmts_kind_e; + +// stmts ::= { stmts } +typedef struct { + file_location *file_loc; + AST_type type_tag; + stmts_kind_e stmts_kind; + stmt_list_t stmt_list; // when stmts_kind != empty_stmts_e +} stmts_t; + +// stmt ::= ident := expr +typedef struct { + file_location *file_loc; + AST_type type_tag; + const char *name; + struct expr_s *expr; + id_use *idu; +} assign_stmt_t; + +// stmt ::= call ident +typedef struct { + file_location *file_loc; + AST_type type_tag; + const char *name; + id_use *idu; +} call_stmt_t; + +// forward declaration for block type +struct block_s; + +// block-stmt ::= block +typedef struct block_stmt_s { + file_location *file_loc; + AST_type type_tag; + struct block_s *block; +} block_stmt_t; + +// if-stmt ::= if condition stmts stmts | if condition stmts +typedef struct { + file_location *file_loc; + AST_type type_tag; + condition_t condition; + stmts_t *then_stmts; + stmts_t *else_stmts; +} if_stmt_t; + +// stmt ::= while condition stmt +typedef struct { + file_location *file_loc; + AST_type type_tag; + condition_t condition; + stmts_t *body; +} while_stmt_t; + +// stmt ::= read ident +typedef struct { + file_location *file_loc; + AST_type type_tag; + const char *name; + id_use *idu; +} read_stmt_t; + +// stmt ::= print expr +typedef struct { + file_location *file_loc; + AST_type type_tag; + expr_t expr; +} print_stmt_t; + +// stmt ::= assign-stmt | call-stmt | if-stmt +// | while-stmt | read-stmt | print-stmt | block-stmt +typedef struct stmt_s { + file_location *file_loc; + AST_type type_tag; + struct stmt_s *next; // for lists this is a part of + stmt_kind_e stmt_kind; + union { + assign_stmt_t assign_stmt; + call_stmt_t call_stmt; + if_stmt_t if_stmt; + while_stmt_t while_stmt; + read_stmt_t read_stmt; + print_stmt_t print_stmt; + block_stmt_t block_stmt; + } data; +} stmt_t; + +// procDecl ::= proc ident block +typedef struct proc_decl_s { + file_location *file_loc; + AST_type type_tag; + struct proc_decl_s *next; // for lists + const char *name; + struct block_s *block; +} proc_decl_t; + +// proc-decls ::= { proc-decl } +typedef struct { + file_location *file_loc; + AST_type type_tag; + proc_decl_t *proc_decls; +} proc_decls_t; + +// ident-list ::= ident | ident-list ident +typedef struct { + file_location *file_loc; + AST_type type_tag; + ident_t *start; +} ident_list_t; + +// var-decl ::= var ident-list +typedef struct var_decl_s { + file_location *file_loc; + AST_type type_tag; + struct var_decl_s *next; // for lists this is a part of + ident_list_t ident_list; +} var_decl_t; + +// var-decls ::= { var-decl } +typedef struct { + file_location *file_loc; + AST_type type_tag; + var_decl_t *var_decls; +} var_decls_t; + +// const-def ::= ident number +typedef struct const_def_s { + file_location *file_loc; + AST_type type_tag; + struct const_def_s *next; // for lists this is a part of + ident_t ident; + number_t number; +} const_def_t; + +// const-def-list ::= { const-def } +typedef struct { + file_location *file_loc; + AST_type type_tag; + const_def_t *start; +} const_def_list_t; + +// const-decl ::= const const-def-list +typedef struct const_decl_s { + file_location *file_loc; + AST_type type_tag; + struct const_decl_s *next; // for lists this is a part of + const_def_list_t const_def_list; +} const_decl_t; + +// const-decls ::= { const-decl } +typedef struct { + file_location *file_loc; + AST_type type_tag; + const_decl_t *start; +} const_decls_t; + +// block ::= begin const-decls var-decls proc-decls stmts +typedef struct block_s { + file_location *file_loc; + AST_type type_tag; + const_decls_t const_decls; + var_decls_t var_decls; + proc_decls_t proc_decls; + stmts_t stmts; +} block_t; + +// program ::= block + +// The AST definition used by bison +typedef union AST_u { + generic_t generic; + block_t block; + const_decls_t const_decls; + const_decl_t const_decl; + const_def_list_t const_def_list; + const_def_t const_def; + var_decls_t var_decls; + var_decl_t var_decl; + ident_list_t ident_list; + proc_decls_t proc_decls; + proc_decl_t proc_decl; + stmts_t stmts; + stmt_list_t stmt_list; + stmt_t stmt; + assign_stmt_t assign_stmt; + call_stmt_t call_stmt; + if_stmt_t if_stmt; + while_stmt_t while_stmt; + read_stmt_t read_stmt; + print_stmt_t print_stmt; + block_stmt_t block_stmt; + condition_t condition; + rel_op_condition_t rel_op_condition; + db_condition_t db_condition; + expr_t expr; + binary_op_expr_t binary_op_expr; + token_t token; + number_t number; + ident_t ident; + empty_t empty; +} AST; + +// Return the file location from an AST +extern file_location *ast_file_loc(AST t); + +// Return the filename from the AST t +extern const char *ast_filename(AST t); + +// Return the line number from the AST t +extern unsigned int ast_line(AST t); + +// Return the type tag of the AST t +extern AST_type ast_type_tag(AST t); + +// Return a pointer to a fresh copy of t +// that has been allocated on the heap +extern AST *ast_heap_copy(AST t); + +// Return an AST for a block which contains the given ASTs. +extern block_t ast_block(token_t begin_tok, const_decls_t const_decls, var_decls_t var_decls, proc_decls_t proc_decls, stmts_t stmts); + +// Return an AST for an empty const decls +extern const_decls_t ast_const_decls_empty(empty_t empty); + +// Return an AST for the const decls +extern const_decls_t ast_const_decls(const_decls_t const_decls, + const_decl_t const_decl); + +// Return an AST for a const_decl +extern const_decl_t ast_const_decl(const_def_list_t const_def_list); + +// Return an AST for const_def_list +extern const_def_list_t ast_const_def_list_singleton(const_def_t const_def); + +// Return an AST for adding to a const_def_list +extern const_def_list_t ast_const_def_list(const_def_list_t const_def_list, + const_def_t const_def); + +// Return an AST for a const-def +extern const_def_t ast_const_def(ident_t ident, number_t number); + +// Return an AST for varDecls that are empty +extern var_decls_t ast_var_decls_empty(empty_t empty); + +// Return an AST varDecls that have some var_decls +extern var_decls_t ast_var_decls(var_decls_t var_decls, var_decl_t var_decl); + +// Return an AST for a var_decl +extern var_decl_t ast_var_decl(ident_list_t ident_list); + +// Return an AST made for one ident +extern ident_list_t ast_ident_list_singleton(ident_t ident); + +// Return an AST made for ident lists +extern ident_list_t ast_ident_list(ident_list_t ident_list, ident_t ident); + +// Return an AST for proc_decls +extern proc_decls_t ast_proc_decls_empty(empty_t empty); + +// Return an AST for proc_decls +extern proc_decls_t ast_proc_decls(proc_decls_t proc_decls, + proc_decl_t proc_decl); + +// Return an AST for a proc_decl +extern proc_decl_t ast_proc_decl(ident_t ident, block_t block); + + +// Return an AST for the list of statements +extern stmts_t ast_stmts_empty(empty_t empty); + +// Return an AST for empty found in the given file location +extern empty_t ast_empty(file_location *file_loc); + +// Return an AST for the list of statements +extern stmts_t ast_stmts(stmt_list_t stmt_list); + +// Return an AST for a list of statements that has stmt as a member +extern stmt_list_t ast_stmt_list_singleton(stmt_t stmt); + +// Return an AST for the list of statements +extern stmt_list_t ast_stmt_list(stmt_list_t stmt_list, stmt_t stmt); + +// Return an AST for the given statement as a more general stmt AST +extern stmt_t ast_stmt_assign(assign_stmt_t s); + +// Return an AST for the given statement as a more general stmt AST +extern stmt_t ast_stmt_call(call_stmt_t s); + +// Return an AST for the given statement as a more general stmt AST +extern stmt_t ast_stmt_block(block_stmt_t s); + +// Return an AST for the given statement as a more general stmt AST +extern stmt_t ast_stmt_if(if_stmt_t s); + +// Return an AST for the given statement as a more general stmt AST +extern stmt_t ast_stmt_while(while_stmt_t s); + +// Return an AST for the given statement as a more general stmt AST +extern stmt_t ast_stmt_read(read_stmt_t s); + +// Return an AST for the given statement as a more general stmt AST +extern stmt_t ast_stmt_print(print_stmt_t s); + +// Return an AST for an assignment statement +extern assign_stmt_t ast_assign_stmt(ident_t ident, expr_t expr); + +// Return an AST for a call statement +extern call_stmt_t ast_call_stmt(ident_t ident); + +// Return an AST for an if-then-else statement +extern if_stmt_t ast_if_then_else_stmt(condition_t condition, + stmts_t then_stmts, stmts_t else_stmts); + +// Return an AST for a (short) if-then statement +// Note that the else part is a NULL pointer +extern if_stmt_t ast_if_then_stmt(condition_t condition, + stmts_t then_stmts); + +// Return an AST for a while statement +extern while_stmt_t ast_while_stmt(condition_t condition, stmts_t body); + +// Return an AST for a read statement +extern read_stmt_t ast_read_stmt(ident_t ident); + +// Return an AST for a print statement +extern print_stmt_t ast_print_stmt(expr_t expr); + +// Return an AST for a block statement +extern block_stmt_t ast_block_stmt(block_t block); + + +// Return an AST for an odd condition +extern db_condition_t ast_db_condition(expr_t dividend, expr_t divisor); + +// Return an AST for an initializer with the given value +extern rel_op_condition_t ast_rel_op_condition(expr_t expr1, token_t rel_op, + expr_t expr2); + +// Return an AST for an odd condition +extern condition_t ast_condition_db(db_condition_t db_cond); + +// Return an AST for a relational condition +extern condition_t ast_condition_rel_op(rel_op_condition_t rel_op_cond); + + +// Return an expression AST for a binary operation expresion +extern expr_t ast_expr_binary_op(binary_op_expr_t e1); + +// Return an expression AST for an identifier +extern expr_t ast_expr_ident(ident_t e); + +// Return an AST for an expression that's a number +extern expr_t ast_expr_number(number_t e); + +// Return an AST for a binary op expression +extern binary_op_expr_t ast_binary_op_expr(expr_t expr1, token_t arith_op, + expr_t expr2); + +// Return an expression AST for a signed expression +extern expr_t ast_expr_signed_expr(token_t sign, expr_t expr); + +// The following are made by the lexer... + +// Return an AST for the given token +extern token_t ast_token(file_location *file_loc, const char *text, int code); + +// Return an AST for an identifier +// found in the file named fn, on line ln, with the given name. +extern ident_t ast_ident(file_location *file_loc, const char *name); + +// Some operations on AST lists + +// Requires: lst is a pointer to a non-circular +// linked list with next pointers +// as in generic_t +// Return a pointer to the last element in lst. +// This only returns NULL if lst == NULL. +extern void *ast_last_list_elem(void *lst); + +// Requires: lst is a pointer to a non-circular +// linked list with next pointers +// as in generic_t +// Return the number of elements in the linked list lst +extern int ast_list_length(void *lst); + +// Requires: lst is a pointer to a non-circular +// linked list with next pointers +// as in generic_t +// Is lst empty? +extern bool ast_list_is_empty(void *lst); + +#endif diff --git a/FromGithub/ast.o b/FromGithub/ast.o new file mode 100644 index 0000000..ea5da78 Binary files /dev/null and b/FromGithub/ast.o differ diff --git a/bof.c b/FromGithub/bof.c old mode 100755 new mode 100644 similarity index 69% rename from bof.c rename to FromGithub/bof.c index 82b2b6a..c42f73b --- a/bof.c +++ b/FromGithub/bof.c @@ -1,193 +1,210 @@ -/* $Id: bof.c,v 1.2 2024/10/23 13:38:20 leavens Exp $ */ -// #include -#include -// #include -#include -#include -#include -#include "bof.h" -#include "utilities.h" - -#define MAGIC "BO32" - -// a type for treating bytes as a word -typedef union { - unsigned char buf[BYTES_PER_WORD]; - word_type w; -} word_pun_t; - -// Open filename for reading as a binary file -// Exit the program with an error if this fails, -// otherwise return the BOFFILE struct for the file -BOFFILE bof_read_open(const char *filename) { - BOFFILE bf; - bf.fileptr = fopen(filename, "rb"); - bf.filename = filename; - - if (bf.fileptr == NULL) { - bail_with_error("Error opening file for reading: %s", filename); - } - - return bf; -} - -// Return the size (in bytes) of bf -size_t bof_file_bytes(BOFFILE bf) -{ - struct stat st; - if (stat(bf.filename, &st) < 0) { - bail_with_error("Cannot stat %s to get its size!", bf.filename); - } - ; - return st.st_size; -} - -// Return true just when bf is at its end, false otherwise -bool bof_at_eof(BOFFILE bf) { - return feof(bf.fileptr); -} - -// Requires: bf is open for reading in binary and has -// at least BYTES_PER_WORD bytes in it -// Return the next word from bf -word_type bof_read_word(BOFFILE bf) -{ - word_pun_t b; - assert(!bof_at_eof(bf)); - size_t bytes_read = bof_read_bytes(bf, BYTES_PER_WORD, b.buf); - if (bytes_read == 0) { - bail_with_error( - "Cannot read a word from %s (got %d bytes), at EOF: %d", - bf.filename, bytes_read, bof_at_eof(bf)); - } - return b.w; -} - -// Requires: bf.fileptr is open for reading in binary -// and buf is of size at least bytes -// Read the given number of bytes into buf and return the number of bytes read -size_t bof_read_bytes(BOFFILE bf, size_t bytes, void *buf) { - int elems_read = fread(buf, bytes, 1, bf.fileptr); - return elems_read; -} - -// Requires: bf is open for reading in binary -// Read the header of bf as a BOFHeader and return that header -// If any errors are encountered, exit with an error message. -BOFHeader bof_read_header(BOFFILE bf) { - BOFHeader ret; - size_t rd = fread(&ret, sizeof(ret), 1, bf.fileptr); - if (rd != 1) { - bail_with_error("Cannot read header from %s", bf.filename); - } - if (!bof_has_correct_magic_number(ret)) { - bail_with_error("Wrong magic number code in file '%s'!", - bf.filename); - } - return ret; - /* - bof_read_bytes(bf, MAGIC_BUFFER_SIZE, &ret.magic); - if (strncmp(ret.magic, MAGIC, MAGIC_BUFFER_SIZE) != 0) { - bail_with_error("File %s is not a BOF format file, bad magic number!", - bf.filename); - } - bof_read_bytes(bf, BYTES_PER_WORD, &ret.text_start_address); - bof_read_bytes(bf, BYTES_PER_WORD, &ret.text_length); - bof_read_bytes(bf, BYTES_PER_WORD, &ret.data_start_address); - bof_read_bytes(bf, BYTES_PER_WORD, &ret.data_length); - bof_read_bytes(bf, BYTES_PER_WORD, &ret.stack_bottom_addr); - return ret; - */ -} - -// Requires: f is open for writing -// Write the magic number in hexadecimal notation on f, followed by a newline; -// Note: this is just for help in writing the documentation -/* -void bof_write_magic(FILE *f) { - fprintf(f, "%s", "0x"); - for (int i = 0; i < MAGIC_BUFFER_SIZE; i++) { - fprintf(f, "%x", MAGIC[i]); - } - fprintf(f, "\n"); -} -*/ - -// Open filename for writing as a binary file -// Exit the program with an error if this fails, -// otherwise return the BOFFILE for it. -BOFFILE bof_write_open(const char *filename) { - BOFFILE bf; - bf.fileptr = fopen(filename, "wb"); - bf.filename = filename; - - if (bf.fileptr == NULL) { - bail_with_error("Error opening file for writing: %s", filename); - } - - return bf; -} - -// Requres: bf is open -// Close the given binary file -// Exit the program with an error if this fails. -void bof_close(BOFFILE bf) -{ - if (fclose(bf.fileptr) != 0) { - bail_with_error("Could not close %s", bf.filename); - } -} - - -// Requires: bf is open for writing in binary. -// Write the given word into bf -// Exit the program with an error if this fails. -extern void bof_write_word(BOFFILE bf, word_type w) -{ - word_pun_t b; - b.w = w; - bof_write_bytes(bf, BYTES_PER_WORD, b.buf); -} - -// Requires: bf is open for writing in binary -// and the size of buf is at least bytes -// Write the given number of bytes from buf into f. -// Exit the program with an error if this fails. -void bof_write_bytes(BOFFILE bf, size_t bytes, - const void *buf) { - size_t wr = fwrite(buf, bytes, 1, bf.fileptr); - if (wr != 1) { - bail_with_error("Cannot write %u bytes to %s", bytes, bf.filename); - } -} - -// Requires: bf is open for writing in binary -// Write the given header to f -// Exit the program with an error if this fails. -void bof_write_header(BOFFILE bf, const BOFHeader hdr) { - size_t wr = fwrite(&hdr, sizeof(BOFHeader), 1, bf.fileptr); - if (wr != 1) { - bail_with_error("Canot write header to %s", bf.filename); - } -} - -// Write the (bits of the) magic number into the header bh. -void bof_write_magic_to_header(BOFHeader *bh) -{ - const char *magic = MAGIC; - for (int i = 0; i < MAGIC_BUFFER_SIZE; i++) { - bh->magic[i] = magic[i]; - } - assert(bof_has_correct_magic_number(*bh)); -} - -// Does the given header have the appropriate magic number? -bool bof_has_correct_magic_number(BOFHeader bh) -{ - char buf[MAGIC_BUFFER_SIZE+1]; - for (int i = 0; i < MAGIC_BUFFER_SIZE; i++) { - buf[i] = bh.magic[i]; - } - buf[MAGIC_BUFFER_SIZE] = '\0'; - return (0 == strncmp(buf, MAGIC, MAGIC_BUFFER_SIZE)); -} +/* $Id: bof.c,v 1.2 2024/10/23 13:38:20 leavens Exp $ */ +// #include +#include +// #include +#include +#include +#include +#include "bof.h" +#include "utilities.h" + +#define MAGIC "BO32" +// this is a comment +// a type for treating bytes as a word +typedef union +{ + unsigned char buf[BYTES_PER_WORD]; + word_type w; +} word_pun_t; + +// Open filename for reading as a binary file +// Exit the program with an error if this fails, +// otherwise return the BOFFILE struct for the file +BOFFILE bof_read_open(const char *filename) +{ + BOFFILE bf; + bf.fileptr = fopen(filename, "rb"); + bf.filename = filename; + + if (bf.fileptr == NULL) + { + bail_with_error("Error opening file for reading: %s", filename); + } + + return bf; +} + +// Return the size (in bytes) of bf +size_t bof_file_bytes(BOFFILE bf) +{ + struct stat st; + if (stat(bf.filename, &st) < 0) + { + bail_with_error("Cannot stat %s to get its size!", bf.filename); + }; + return st.st_size; +} + +// Return true just when bf is at its end, false otherwise +bool bof_at_eof(BOFFILE bf) +{ + return feof(bf.fileptr); +} + +// Requires: bf is open for reading in binary and has +// at least BYTES_PER_WORD bytes in it +// Return the next word from bf +word_type bof_read_word(BOFFILE bf) +{ + word_pun_t b; + assert(!bof_at_eof(bf)); + size_t bytes_read = bof_read_bytes(bf, BYTES_PER_WORD, b.buf); + if (bytes_read == 0) + { + bail_with_error( + "Cannot read a word from %s (got %d bytes), at EOF: %d", + bf.filename, bytes_read, bof_at_eof(bf)); + } + return b.w; +} + +// Requires: bf.fileptr is open for reading in binary +// and buf is of size at least bytes +// Read the given number of bytes into buf and return the number of bytes read +size_t bof_read_bytes(BOFFILE bf, size_t bytes, void *buf) +{ + int elems_read = fread(buf, bytes, 1, bf.fileptr); + return elems_read; +} + +// Requires: bf is open for reading in binary +// Read the header of bf as a BOFHeader and return that header +// If any errors are encountered, exit with an error message. +BOFHeader bof_read_header(BOFFILE bf) +{ + BOFHeader ret; + size_t rd = fread(&ret, sizeof(ret), 1, bf.fileptr); + if (rd != 1) + { + bail_with_error("Cannot read header from %s", bf.filename); + } + if (!bof_has_correct_magic_number(ret)) + { + bail_with_error("Wrong magic number code in file '%s'!", + bf.filename); + } + return ret; + /* + bof_read_bytes(bf, MAGIC_BUFFER_SIZE, &ret.magic); + if (strncmp(ret.magic, MAGIC, MAGIC_BUFFER_SIZE) != 0) { + bail_with_error("File %s is not a BOF format file, bad magic number!", + bf.filename); + } + bof_read_bytes(bf, BYTES_PER_WORD, &ret.text_start_address); + bof_read_bytes(bf, BYTES_PER_WORD, &ret.text_length); + bof_read_bytes(bf, BYTES_PER_WORD, &ret.data_start_address); + bof_read_bytes(bf, BYTES_PER_WORD, &ret.data_length); + bof_read_bytes(bf, BYTES_PER_WORD, &ret.stack_bottom_addr); + return ret; + */ +} + +// Requires: f is open for writing +// Write the magic number in hexadecimal notation on f, followed by a newline; +// Note: this is just for help in writing the documentation +/* +void bof_write_magic(FILE *f) { + fprintf(f, "%s", "0x"); + for (int i = 0; i < MAGIC_BUFFER_SIZE; i++) { + fprintf(f, "%x", MAGIC[i]); + } + fprintf(f, "\n"); +} +*/ + +// Open filename for writing as a binary file +// Exit the program with an error if this fails, +// otherwise return the BOFFILE for it. +BOFFILE bof_write_open(const char *filename) +{ + BOFFILE bf; + bf.fileptr = fopen(filename, "wb"); + bf.filename = filename; + + if (bf.fileptr == NULL) + { + bail_with_error("Error opening file for writing: %s", filename); + } + + return bf; +} + +// Requres: bf is open +// Close the given binary file +// Exit the program with an error if this fails. +void bof_close(BOFFILE bf) +{ + if (fclose(bf.fileptr) != 0) + { + bail_with_error("Could not close %s", bf.filename); + } +} + +// Requires: bf is open for writing in binary. +// Write the given word into bf +// Exit the program with an error if this fails. +extern void bof_write_word(BOFFILE bf, word_type w) +{ + word_pun_t b; + b.w = w; + bof_write_bytes(bf, BYTES_PER_WORD, b.buf); +} + +// Requires: bf is open for writing in binary +// and the size of buf is at least bytes +// Write the given number of bytes from buf into f. +// Exit the program with an error if this fails. +void bof_write_bytes(BOFFILE bf, size_t bytes, + const void *buf) +{ + size_t wr = fwrite(buf, bytes, 1, bf.fileptr); + if (wr != 1) + { + bail_with_error("Cannot write %u bytes to %s", bytes, bf.filename); + } +} + +// Requires: bf is open for writing in binary +// Write the given header to f +// Exit the program with an error if this fails. +void bof_write_header(BOFFILE bf, const BOFHeader hdr) +{ + size_t wr = fwrite(&hdr, sizeof(BOFHeader), 1, bf.fileptr); + if (wr != 1) + { + bail_with_error("Canot write header to %s", bf.filename); + } +} + +// Write the (bits of the) magic number into the header bh. +void bof_write_magic_to_header(BOFHeader *bh) +{ + const char *magic = MAGIC; + for (int i = 0; i < MAGIC_BUFFER_SIZE; i++) + { + bh->magic[i] = magic[i]; + } + assert(bof_has_correct_magic_number(*bh)); +} + +// Does the given header have the appropriate magic number? +bool bof_has_correct_magic_number(BOFHeader bh) +{ + char buf[MAGIC_BUFFER_SIZE + 1]; + for (int i = 0; i < MAGIC_BUFFER_SIZE; i++) + { + buf[i] = bh.magic[i]; + } + buf[MAGIC_BUFFER_SIZE] = '\0'; + return (0 == strncmp(buf, MAGIC, MAGIC_BUFFER_SIZE)); +} diff --git a/bof.h b/FromGithub/bof.h old mode 100755 new mode 100644 similarity index 97% rename from bof.h rename to FromGithub/bof.h index 0201806..7041917 --- a/bof.h +++ b/FromGithub/bof.h @@ -1,88 +1,88 @@ -/* $Id: bof.h,v 1.2 2024/10/23 13:38:20 leavens Exp $ */ -// Binary Object File Format (for the SSM) -#ifndef _BOF_H -#define _BOF_H -#include -#include -#include -#include "machine_types.h" - -#define MAGIC_BUFFER_SIZE 4 - -typedef struct { // Field magic should hold value of MAGIC (with no null char) - char magic[MAGIC_BUFFER_SIZE]; - word_type text_start_address; // word address to start running (PC) - word_type text_length; // size of the text section in words - word_type data_start_address; // word address of static data (GP) - word_type data_length; // size of data section in words - word_type stack_bottom_addr; // word address of stack "bottom" (FP) -} BOFHeader; - -// a type for Binary Output Files -typedef struct { - FILE *fileptr; - const char *filename; -} BOFFILE; - -// Open filename for reading as a binary file -// Exit the program with an error if this fails, -// otherwise return the FILE pointer to the open file. -extern BOFFILE bof_read_open(const char *filename); - -// Return the size (in bytes) of bf -extern size_t bof_file_bytes(BOFFILE bf); - -// Return true just when bf is at its end, false otherwise -extern bool bof_at_eof(BOFFILE bf); - -// Requires: bf is open for reading in binary and has -// at least 1 word (2 bytes) available to read -// Return the next word from bf -extern word_type bof_read_word(BOFFILE bf); - -// Requires: bf is open for reading in binary and -// buf is of size at least bytes -// Read the given number of bytes into buf and return the number of bytes read -size_t bof_read_bytes(BOFFILE bf, size_t bytes, void *buf); - -// Requires: bf is open for reading in binary -// Read the header of bf as a BOFHeader and return that header -// If any errors are encountered, exit with an error message. -extern BOFHeader bof_read_header(BOFFILE); - -// Open filename for writing as a binary file -// Exit the program with an error if this fails, -// otherwise return the BOFFILE for it. -extern BOFFILE bof_write_open(const char *filename); - -// Requres: bf is open -// Close the given binary file -// Exit the program with an error if this fails. -extern void bof_close(BOFFILE bf); - -// Requires: bf is open for writing in binary -// Write the given word into bf. -// Exit the program with an error if this fails. -extern void bof_write_word(BOFFILE bf, word_type w); - -// Requires: bf is open for writing in binary -// and the size of buf is at least bytes -// Write the given number of bytes from buf into f. -// Exit the program with an error if this fails. -extern void bof_write_bytes(BOFFILE bf, size_t bytes, - const void *buf); - -// Requires: bf is open for writing in binary -// Write the given header to f -// Exit the program with an error if this fails. -extern void bof_write_header(BOFFILE bf, const BOFHeader hdr); - -// Write the (bits of the) magic number into the header *bh. -extern void bof_write_magic_to_header(BOFHeader *bh); - -// Does the given header have the appropriate magic number? -bool bof_has_correct_magic_number(BOFHeader bh); - -// The following line is for the manual (i.e., the document itself)y -// ... -#endif +/* $Id: bof.h,v 1.2 2024/10/23 13:38:20 leavens Exp $ */ +// Binary Object File Format (for the SSM) +#ifndef _BOF_H +#define _BOF_H +#include +#include +#include +#include "machine_types.h" + +#define MAGIC_BUFFER_SIZE 4 + +typedef struct { // Field magic should hold value of MAGIC (with no null char) + char magic[MAGIC_BUFFER_SIZE]; + word_type text_start_address; // word address to start running (PC) + word_type text_length; // size of the text section in words + word_type data_start_address; // word address of static data (GP) + word_type data_length; // size of data section in words + word_type stack_bottom_addr; // word address of stack "bottom" (FP) +} BOFHeader; + +// a type for Binary Output Files +typedef struct { + FILE *fileptr; + const char *filename; +} BOFFILE; + +// Open filename for reading as a binary file +// Exit the program with an error if this fails, +// otherwise return the FILE pointer to the open file. +extern BOFFILE bof_read_open(const char *filename); + +// Return the size (in bytes) of bf +extern size_t bof_file_bytes(BOFFILE bf); + +// Return true just when bf is at its end, false otherwise +extern bool bof_at_eof(BOFFILE bf); + +// Requires: bf is open for reading in binary and has +// at least 1 word (2 bytes) available to read +// Return the next word from bf +extern word_type bof_read_word(BOFFILE bf); + +// Requires: bf is open for reading in binary and +// buf is of size at least bytes +// Read the given number of bytes into buf and return the number of bytes read +size_t bof_read_bytes(BOFFILE bf, size_t bytes, void *buf); + +// Requires: bf is open for reading in binary +// Read the header of bf as a BOFHeader and return that header +// If any errors are encountered, exit with an error message. +extern BOFHeader bof_read_header(BOFFILE); + +// Open filename for writing as a binary file +// Exit the program with an error if this fails, +// otherwise return the BOFFILE for it. +extern BOFFILE bof_write_open(const char *filename); + +// Requres: bf is open +// Close the given binary file +// Exit the program with an error if this fails. +extern void bof_close(BOFFILE bf); + +// Requires: bf is open for writing in binary +// Write the given word into bf. +// Exit the program with an error if this fails. +extern void bof_write_word(BOFFILE bf, word_type w); + +// Requires: bf is open for writing in binary +// and the size of buf is at least bytes +// Write the given number of bytes from buf into f. +// Exit the program with an error if this fails. +extern void bof_write_bytes(BOFFILE bf, size_t bytes, + const void *buf); + +// Requires: bf is open for writing in binary +// Write the given header to f +// Exit the program with an error if this fails. +extern void bof_write_header(BOFFILE bf, const BOFHeader hdr); + +// Write the (bits of the) magic number into the header *bh. +extern void bof_write_magic_to_header(BOFHeader *bh); + +// Does the given header have the appropriate magic number? +bool bof_has_correct_magic_number(BOFHeader bh); + +// The following line is for the manual (i.e., the document itself)y +// ... +#endif diff --git a/FromGithub/bof.o b/FromGithub/bof.o new file mode 100644 index 0000000..4e2c359 Binary files /dev/null and b/FromGithub/bof.o differ diff --git a/char-inputs.txt b/FromGithub/char-inputs.txt old mode 100755 new mode 100644 similarity index 100% rename from char-inputs.txt rename to FromGithub/char-inputs.txt diff --git a/code.c b/FromGithub/code.c old mode 100755 new mode 100644 similarity index 89% rename from code.c rename to FromGithub/code.c index 1e460ab..f5f181f --- a/code.c +++ b/FromGithub/code.c @@ -1,462 +1,494 @@ -/* $Id: code.c,v 1.29 2024/11/11 23:01:08 leavens Exp $ */ -#include -#include -#include -#include "utilities.h" -#include "code.h" -#include "regname.h" - -// Return a fresh code struct, with next pointer NULL -// containing the given instruction instr. -// If there is not enough space, bail with an error, -// so this will never return NULL. -static code *code_create(bin_instr_t instr) -{ - code *ret = (code *)malloc(sizeof(code)); - if (ret == NULL) { - bail_with_error("Not enough space to allocate a code struct!"); - } - ret->next = NULL; - ret->instr = instr; - return ret; -} - -// --- computational format instructions as in the SSM Manual's table 3 --- - -// return a freshly allocated computational-format instruction -static code *create_comp_instr(reg_num_type t, offset_type ot, reg_num_type s, - offset_type os, func0_code fc) -{ - comp_instr_t ci; - ci.op = COMP_O; - ci.rt = t; - ci.ot = ot; - ci.rs = s; - ci.os = os; - ci.func = fc; - bin_instr_t bi; - bi.comp = ci; - return code_create(bi); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_nop() -{ - return create_comp_instr(0,0,0,0,NOP_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_add(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os) -{ - return create_comp_instr(t, ot, s, os, ADD_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_sub(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os) -{ - return create_comp_instr(t, ot, s, os, SUB_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_cpw(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os) -{ - return create_comp_instr(t, ot, s, os, CPW_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_cpr(reg_num_type t, reg_num_type s) -{ - return create_comp_instr(t, 0, s, 0, CPR_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_and(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os) -{ - return create_comp_instr(t, ot, s, os, AND_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_bor(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os) -{ - return create_comp_instr(t, ot, s, os, BOR_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_nor(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os) -{ - return create_comp_instr(t, ot, s, os, NOR_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_xor(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os) -{ - return create_comp_instr(t, ot, s, os, XOR_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_lwr(reg_num_type t, reg_num_type s, offset_type os) -{ - return create_comp_instr(t, 0, s, os, LWR_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_swr(reg_num_type t, offset_type ot, reg_num_type s) -{ - return create_comp_instr(t, ot, s, 0, SWR_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_sca(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os) -{ - return create_comp_instr(t, ot, s, os, SCA_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_lwi(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os) -{ - return create_comp_instr(t, ot, s, os, LWI_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_neg(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os) -{ - return create_comp_instr(t, ot, s, os, NEG_F); -} - - -// --- other computational format instructions, in SSM Manual's table 4 --- - -// return a freshly allocated computational-format instruction -static code *create_other_comp_instr(reg_num_type t, offset_type o, - arg_type a, func1_code fc) -{ - other_comp_instr_t oci; - oci.op = OTHC_O; - oci.reg = t; - oci.offset = o; - oci.arg = a; - oci.func = fc; - bin_instr_t bi; - bi.othc = oci; - return code_create(bi); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_lit(reg_num_type t, offset_type ot, immediate_type i) -{ - return create_other_comp_instr(t, ot, i, LIT_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_ari(reg_num_type r, immediate_type i) -{ - return create_other_comp_instr(r, 0, i, ARI_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_sri(reg_num_type r, immediate_type i) -{ - return create_other_comp_instr(r, 0, i, SRI_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_mul(reg_num_type s, offset_type o) -{ - return create_other_comp_instr(s, o, 0, MUL_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_div(reg_num_type s, offset_type o) -{ - return create_other_comp_instr(s, o, 0, DIV_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_cfhi(reg_num_type t, offset_type o) -{ - return create_other_comp_instr(t, o, 0, CFHI_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_cflo(reg_num_type t, offset_type o) -{ - return create_other_comp_instr(t, o, 0, CFLO_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_sll(reg_num_type t, offset_type o, shift_type h) -{ - return create_other_comp_instr(t, o, h, SLL_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_srl(reg_num_type t, offset_type o, shift_type h) -{ - return create_other_comp_instr(t, o, h, SLL_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_jmp(reg_num_type s, offset_type o) -{ - return create_other_comp_instr(s, o, 0, JMP_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_csi(reg_num_type s, offset_type o) -{ - return create_other_comp_instr(s, o, 0, CSI_F); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_jrel(offset_type o) -{ - return create_other_comp_instr(0, 0, o, JREL_F); -} - - -// --- immediate format instructions, in SSM Manual's table 5 --- - -// return a fresh immediate-type instruction -// (with a signed immediate operand) -static code *create_immed_instr(op_code op, reg_num_type r, - offset_type o, immediate_type i) -{ - immed_instr_t ii; - ii.op = op; - ii.reg = r; - ii.offset = o; - ii.immed = i; // this is sign extended by the VM, not here! - bin_instr_t bi; - bi.immed = ii; - return code_create(bi); -} - -// return a fresh immediate-type instruction -// (with an unsigned immediate operand) -static code *create_uimmed_instr(op_code op, reg_num_type r, - offset_type o, uimmed_type u) -{ - uimmed_instr_t ui; - ui.op = op; - ui.reg = r; - ui.offset = o; - ui.uimmed = u; - bin_instr_t bi; - bi.uimmed = ui; - return code_create(bi); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_addi(reg_num_type r, offset_type o, immediate_type i) -{ - return create_immed_instr(ADDI_O, r, o, i); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_andi(reg_num_type r, offset_type o, uimmed_type u) -{ - return create_uimmed_instr(ANDI_O, r, o, u); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_bori(reg_num_type r, offset_type o, uimmed_type u) -{ - return create_uimmed_instr(BORI_O, r, o, u); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_nori(reg_num_type r, offset_type o, uimmed_type u) -{ - return create_uimmed_instr(NORI_O, r, o, u); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_xori(reg_num_type r, offset_type o, uimmed_type u) -{ - return create_uimmed_instr(XORI_O, r, o, u); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_beq(reg_num_type r, offset_type o, immediate_type i) -{ - return create_immed_instr(BEQ_O, r, o, i); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_bgez(reg_num_type r, offset_type o, immediate_type i) -{ - return create_immed_instr(BGEZ_O, r, o, i); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_bgtz(reg_num_type r, offset_type o, immediate_type i) -{ - return create_immed_instr(BGTZ_O, r, o, i); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_blez(reg_num_type r, offset_type o, immediate_type i) -{ - return create_immed_instr(BLEZ_O, r, o, i); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_bltz(reg_num_type r, offset_type o, immediate_type i) -{ - return create_immed_instr(BLTZ_O, r, o, i); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_bne(reg_num_type r, offset_type o, immediate_type i) -{ - return create_immed_instr(BNE_O, r, o, i); -} - -// --- jump format instructions, in SSM Manual's table 6 --- - -// return a fresh jump-type instruction -static code *create_jump_instr(op_code op, address_type a) -{ - jump_instr_t ji; - ji.op = op; - ji.addr = a; - bin_instr_t bi; - bi.jump = ji; - return code_create(bi); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_jmpa(address_type a) -{ - return create_jump_instr(JMPA_O, a); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_call(address_type a) -{ - code *ret = create_jump_instr(CALL_O, a); - return ret; -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_rtn() -{ - code *ret = create_jump_instr(RTN_O, 0); - return ret; -} - -// --- system call instructions, in SSM Manual's table 7 --- - -// return a fresh syscall-type instruction -static code *create_syscall_instr(syscall_type t, reg_num_type r, offset_type o) -{ - syscall_instr_t si; - si.op = OTHC_O; - si.reg = r; - si.offset = o; - si.code = t; - si.func = SYS_F; - bin_instr_t bi; - bi.syscall = si; - return code_create(bi); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_exit(offset_type o) -{ - return create_syscall_instr(exit_sc, 0, o); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_pstr(reg_num_type s, offset_type o) -{ - return create_syscall_instr(print_str_sc, s, o); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_pint(reg_num_type s, offset_type o) -{ - return create_syscall_instr(print_int_sc, s, o); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_pch(reg_num_type s, offset_type o) -{ - return create_syscall_instr(print_char_sc, s, o); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_rch(reg_num_type t, offset_type o) -{ - return create_syscall_instr(read_char_sc, t, o); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_stra() -{ - return create_syscall_instr(start_tracing_sc,0,0); -} - -// Create and return a fresh instruction -// with the named mnemonic and parameters -code *code_notr() -{ - return create_syscall_instr(stop_tracing_sc,0,0); -} - +/* $Id: code.c,v 1.29 2024/11/11 23:01:08 leavens Exp $ */ +#include +#include +#include +#include "utilities.h" +#include "code.h" +#include "regname.h" + +// Return a fresh code struct, with next pointer NULL +// containing the given instruction instr. +// If there is not enough space, bail with an error, +// so this will never return NULL. +static code *code_create(bin_instr_t instr) +{ + code *ret = (code *)malloc(sizeof(code)); + if (ret == NULL) { + bail_with_error("Not enough space to allocate a code struct!"); + } + ret->next = NULL; + ret->instr = instr; + return ret; +} + +// --- computational format instructions as in the SSM Manual's table 3 --- + +// return a freshly allocated computational-format instruction +static code *create_comp_instr(reg_num_type t, offset_type ot, reg_num_type s, + offset_type os, func0_code fc) +{ + comp_instr_t ci; + ci.op = COMP_O; + ci.rt = t; + ci.ot = ot; + ci.rs = s; + ci.os = os; + ci.func = fc; + bin_instr_t bi; + bi.comp = ci; + return code_create(bi); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_nop() +{ + return create_comp_instr(0,0,0,0,NOP_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_add(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os) +{ + return create_comp_instr(t, ot, s, os, ADD_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_sub(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os) +{ + return create_comp_instr(t, ot, s, os, SUB_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_cpw(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os) +{ + return create_comp_instr(t, ot, s, os, CPW_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_cpr(reg_num_type t, reg_num_type s) +{ + return create_comp_instr(t, 0, s, 0, CPR_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_and(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os) +{ + return create_comp_instr(t, ot, s, os, AND_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_bor(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os) +{ + return create_comp_instr(t, ot, s, os, BOR_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_nor(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os) +{ + return create_comp_instr(t, ot, s, os, NOR_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_xor(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os) +{ + return create_comp_instr(t, ot, s, os, XOR_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_lwr(reg_num_type t, reg_num_type s, offset_type os) +{ + return create_comp_instr(t, 0, s, os, LWR_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_swr(reg_num_type t, offset_type ot, reg_num_type s) +{ + return create_comp_instr(t, ot, s, 0, SWR_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_sca(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os) +{ + return create_comp_instr(t, ot, s, os, SCA_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_lwi(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os) +{ + return create_comp_instr(t, ot, s, os, LWI_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_neg(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os) +{ + return create_comp_instr(t, ot, s, os, NEG_F); +} + + +// --- other computational format instructions, in SSM Manual's table 4 --- + +// return a freshly allocated computational-format instruction +static code *create_other_comp_instr(reg_num_type t, offset_type o, + arg_type a, func1_code fc) +{ + other_comp_instr_t oci; + oci.op = OTHC_O; + oci.reg = t; + oci.offset = o; + oci.arg = a; + oci.func = fc; + bin_instr_t bi; + bi.othc = oci; + return code_create(bi); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_lit(reg_num_type t, offset_type ot, immediate_type i) +{ + return create_other_comp_instr(t, ot, i, LIT_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_ari(reg_num_type r, immediate_type i) +{ + return create_other_comp_instr(r, 0, i, ARI_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_sri(reg_num_type r, immediate_type i) +{ + return create_other_comp_instr(r, 0, i, SRI_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_mul(reg_num_type s, offset_type o) +{ + return create_other_comp_instr(s, o, 0, MUL_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_div(reg_num_type s, offset_type o) +{ + return create_other_comp_instr(s, o, 0, DIV_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_cfhi(reg_num_type t, offset_type o) +{ + return create_other_comp_instr(t, o, 0, CFHI_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_cflo(reg_num_type t, offset_type o) +{ + return create_other_comp_instr(t, o, 0, CFLO_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_sll(reg_num_type t, offset_type o, shift_type h) +{ + return create_other_comp_instr(t, o, h, SLL_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_srl(reg_num_type t, offset_type o, shift_type h) +{ + return create_other_comp_instr(t, o, h, SLL_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_jmp(reg_num_type s, offset_type o) +{ + return create_other_comp_instr(s, o, 0, JMP_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_csi(reg_num_type s, offset_type o) +{ + return create_other_comp_instr(s, o, 0, CSI_F); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_jrel(offset_type o) +{ + return create_other_comp_instr(0, 0, o, JREL_F); +} + + +// --- immediate format instructions, in SSM Manual's table 5 --- + +// return a fresh immediate-type instruction +// (with a signed immediate operand) +static code *create_immed_instr(op_code op, reg_num_type r, + offset_type o, immediate_type i) +{ + immed_instr_t ii; + ii.op = op; + ii.reg = r; + ii.offset = o; + ii.immed = i; // this is sign extended by the VM, not here! + bin_instr_t bi; + bi.immed = ii; + return code_create(bi); +} + +// return a fresh immediate-type instruction +// (with an unsigned immediate operand) +static code *create_uimmed_instr(op_code op, reg_num_type r, + offset_type o, uimmed_type u) +{ + uimmed_instr_t ui; + ui.op = op; + ui.reg = r; + ui.offset = o; + ui.uimmed = u; + bin_instr_t bi; + bi.uimmed = ui; + return code_create(bi); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_addi(reg_num_type r, offset_type o, immediate_type i) +{ + return create_immed_instr(ADDI_O, r, o, i); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_andi(reg_num_type r, offset_type o, uimmed_type u) +{ + return create_uimmed_instr(ANDI_O, r, o, u); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_bori(reg_num_type r, offset_type o, uimmed_type u) +{ + return create_uimmed_instr(BORI_O, r, o, u); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_nori(reg_num_type r, offset_type o, uimmed_type u) +{ + return create_uimmed_instr(NORI_O, r, o, u); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_xori(reg_num_type r, offset_type o, uimmed_type u) +{ + return create_uimmed_instr(XORI_O, r, o, u); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_beq(reg_num_type r, offset_type o, immediate_type i) +{ + return create_immed_instr(BEQ_O, r, o, i); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_bgez(reg_num_type r, offset_type o, immediate_type i) +{ + return create_immed_instr(BGEZ_O, r, o, i); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_bgtz(reg_num_type r, offset_type o, immediate_type i) +{ + return create_immed_instr(BGTZ_O, r, o, i); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_blez(reg_num_type r, offset_type o, immediate_type i) +{ + return create_immed_instr(BLEZ_O, r, o, i); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_bltz(reg_num_type r, offset_type o, immediate_type i) +{ + return create_immed_instr(BLTZ_O, r, o, i); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_bne(reg_num_type r, offset_type o, immediate_type i) +{ + return create_immed_instr(BNE_O, r, o, i); +} + +// --- jump format instructions, in SSM Manual's table 6 --- + +// return a fresh jump-type instruction +static code *create_jump_instr(op_code op, address_type a) +{ + jump_instr_t ji; + ji.op = op; + ji.addr = a; + bin_instr_t bi; + bi.jump = ji; + return code_create(bi); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_jmpa(address_type a) +{ + return create_jump_instr(JMPA_O, a); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_call(address_type a) +{ + code *ret = create_jump_instr(CALL_O, a); + return ret; +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_rtn() +{ + code *ret = create_jump_instr(RTN_O, 0); + return ret; +} + +// --- system call instructions, in SSM Manual's table 7 --- + +// return a fresh syscall-type instruction +static code *create_syscall_instr(syscall_type t, reg_num_type r, offset_type o) +{ + syscall_instr_t si; + si.op = OTHC_O; + si.reg = r; + si.offset = o; + si.code = t; + si.func = SYS_F; + bin_instr_t bi; + bi.syscall = si; + return code_create(bi); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_exit(offset_type o) +{ + return create_syscall_instr(exit_sc, 0, o); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_pstr(reg_num_type s, offset_type o) +{ + return create_syscall_instr(print_str_sc, s, o); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_pint(reg_num_type s, offset_type o) +{ + return create_syscall_instr(print_int_sc, s, o); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_pch(reg_num_type s, offset_type o) +{ + return create_syscall_instr(print_char_sc, s, o); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_rch(reg_num_type t, offset_type o) +{ + return create_syscall_instr(read_char_sc, t, o); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_stra() +{ + return create_syscall_instr(start_tracing_sc,0,0); +} + +// Create and return a fresh instruction +// with the named mnemonic and parameters +code *code_notr() +{ + return create_syscall_instr(stop_tracing_sc,0,0); +} + +#define MINIMAL_STACK_ALLOC_IN_WORDS 12 +#define MINIMAL_STACK_ALLOC_BYTES (BYTES_PER_WORD*MINIMAL_STACK_ALLOC_IN_WORDS) + +// Set up the runtime stack for a procedure, +// where the static link is found in register $a0. +// Modifies when executed, the SP register, the FP register, +// and memory from SP to SP - MINIMAL_STACK_ALLOC_BYTES +// (inclusive) +code_seq code_save_registers_for_AR() +{ + // assume that SP is pointing to the lowest local storage already allocated + code_seq ret; + // push stack_pointer at word index 0 - 1 from current SP + ret = code_seq_singleton(code_swr(SP, SP, -1)); + // push the frame pointer (dynamic link) at word index -2 + code_seq_add_to_end(&ret, code_swr(SP, FP, -2)); + // save SP into FP register so FP points to the base of the AR + code_seq_add_to_end(&ret, code_add(0, SP, FP,ADD_F)); + // allocate the space on the stack, by subtracting from SP + code_seq_add_to_end(&ret, code_addi(SP, SP, - MINIMAL_STACK_ALLOC_BYTES)); + // push the static link at word index -3 + code_seq_add_to_end(&ret, code_swr(FP, GP, -3)); + // push the return address at word index 3 + code_seq_add_to_end(&ret, code_swr(FP, RA, -4)); + // save the registers $s0 to $s7 (inclusive) + int idx = -5; + for (int rn = GP; rn <= RA; rn++) { + code_seq_add_to_end(&ret, code_swr(FP, rn, idx--)); + } + return ret; +} + diff --git a/code.h b/FromGithub/code.h old mode 100755 new mode 100644 similarity index 96% rename from code.h rename to FromGithub/code.h index 5bb188d..5df0a9d --- a/code.h +++ b/FromGithub/code.h @@ -1,221 +1,230 @@ -/* $Id: code.h,v 1.23 2024/11/10 21:09:43 leavens Exp $ */ -#ifndef _CODE_H -#define _CODE_H -#include -#include "machine_types.h" -#include "instruction.h" - -// SSM assembly language instructions (that can be in linked lists) -typedef struct code_s { - struct code_s *next; - bin_instr_t instr; -} code; - -// Code creation functions below - -// --- computational format instructions from table 3 of the SSM Manual --- - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_nop(); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_add(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_sub(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_cpw(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_cpr(reg_num_type t, reg_num_type s); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_and(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_bor(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_nor(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_xor(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_lwr(reg_num_type t, reg_num_type s, offset_type os); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_swr(reg_num_type t, offset_type ot, reg_num_type s); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_sca(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_lwi(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_neg(reg_num_type t, offset_type ot, - reg_num_type s, offset_type os); - -// --- other computational format instructions from table 4 --- - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_lit(reg_num_type t, offset_type o, - immediate_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_ari(reg_num_type r, immediate_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_sri(reg_num_type r, immediate_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_mul(reg_num_type s, offset_type o); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_div(reg_num_type s, offset_type o); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_cfhi(reg_num_type t, offset_type o); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_cflo(reg_num_type t, offset_type o); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_sll(reg_num_type t, offset_type o, shift_type h); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_srl(reg_num_type t, offset_type o, shift_type h); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_jmp(reg_num_type s, offset_type o); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_csi(reg_num_type s, offset_type o); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_jrel(offset_type o); - -// --- immediate format instructions from table 5 of the SSM Manual --- - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_addi(reg_num_type r, offset_type o, immediate_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_andi(reg_num_type r, offset_type o, uimmed_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_bori(reg_num_type r, offset_type o, uimmed_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_nori(reg_num_type r, offset_type o, uimmed_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_beq(reg_num_type r, offset_type o, immediate_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_bgez(reg_num_type r, offset_type o, immediate_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_bgtz(reg_num_type r, offset_type o, immediate_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_blez(reg_num_type r, offset_type o, immediate_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_bltz(reg_num_type r, offset_type o, immediate_type i); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_bne(reg_num_type r, offset_type o, immediate_type i); - -// --- jump format instructions from table 6 of the SSM Manual --- - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_jmpa(address_type a); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_call(address_type a); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_rtn(); - -// --- system calls from table 7 of the SSM Manual --- - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_exit(offset_type o); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_pstr(reg_num_type s, offset_type o); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_pint(reg_num_type s, offset_type o); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_pch(reg_num_type s, offset_type o); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_rch(reg_num_type t, offset_type o); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_stra(); - -// Create and return a fresh instruction -// with the named mnemonic and parameters -extern code *code_notr(); - -#endif +/* $Id: code.h,v 1.23 2024/11/10 21:09:43 leavens Exp $ */ +#ifndef _CODE_H +#define _CODE_H +#include +#include "machine_types.h" +#include "instruction.h" +#include "code_seq.h" + +// SSM assembly language instructions (that can be in linked lists) +typedef struct code_s { + struct code_s *next; + bin_instr_t instr; +} code; + +// Code creation functions below + +// --- computational format instructions from table 3 of the SSM Manual --- + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_nop(); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_add(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_sub(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_cpw(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_cpr(reg_num_type t, reg_num_type s); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_and(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_bor(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_nor(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_xor(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_lwr(reg_num_type t, reg_num_type s, offset_type os); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_swr(reg_num_type t, offset_type ot, reg_num_type s); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_sca(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_lwi(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_neg(reg_num_type t, offset_type ot, + reg_num_type s, offset_type os); + +// --- other computational format instructions from table 4 --- + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_lit(reg_num_type t, offset_type o, + immediate_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_ari(reg_num_type r, immediate_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_sri(reg_num_type r, immediate_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_mul(reg_num_type s, offset_type o); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_div(reg_num_type s, offset_type o); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_cfhi(reg_num_type t, offset_type o); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_cflo(reg_num_type t, offset_type o); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_sll(reg_num_type t, offset_type o, shift_type h); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_srl(reg_num_type t, offset_type o, shift_type h); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_jmp(reg_num_type s, offset_type o); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_csi(reg_num_type s, offset_type o); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_jrel(offset_type o); + +// --- immediate format instructions from table 5 of the SSM Manual --- + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_addi(reg_num_type r, offset_type o, immediate_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_andi(reg_num_type r, offset_type o, uimmed_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_bori(reg_num_type r, offset_type o, uimmed_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_nori(reg_num_type r, offset_type o, uimmed_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_beq(reg_num_type r, offset_type o, immediate_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_bgez(reg_num_type r, offset_type o, immediate_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_bgtz(reg_num_type r, offset_type o, immediate_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_blez(reg_num_type r, offset_type o, immediate_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_bltz(reg_num_type r, offset_type o, immediate_type i); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_bne(reg_num_type r, offset_type o, immediate_type i); + +// --- jump format instructions from table 6 of the SSM Manual --- + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_jmpa(address_type a); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_call(address_type a); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_rtn(); + +// --- system calls from table 7 of the SSM Manual --- + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_exit(offset_type o); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_pstr(reg_num_type s, offset_type o); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_pint(reg_num_type s, offset_type o); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_pch(reg_num_type s, offset_type o); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_rch(reg_num_type t, offset_type o); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_stra(); + +// Create and return a fresh instruction +// with the named mnemonic and parameters +extern code *code_notr(); + +// Set up the runtime stack for a procedure, +// where the static link is found in register $a0. +// Modifies when executed, the SP register, the FP register, +// and memory from SP to SP - MINIMAL_STACK_ALLOC_BYTES +// (inclusive) +extern code_seq code_save_registers_for_AR(); + + +#endif diff --git a/FromGithub/code.o b/FromGithub/code.o new file mode 100644 index 0000000..c79c028 Binary files /dev/null and b/FromGithub/code.o differ diff --git a/code_seq.c b/FromGithub/code_seq.c old mode 100755 new mode 100644 similarity index 95% rename from code_seq.c rename to FromGithub/code_seq.c index 5c8fc2a..29be4ac --- a/code_seq.c +++ b/FromGithub/code_seq.c @@ -1,135 +1,137 @@ -/* $Id: code_seq.c,v 1.4 2024/11/08 21:01:43 leavens Exp $ */ -#include -#include -#include -#include "utilities.h" -#include "regname.h" -#include "code_seq.h" - -static void code_seq_okay(code_seq seq) -{ - // seq.first and seq.last are either both null or both not null - assert((seq.first == NULL) == (seq.last == NULL)); -} - -// Return an empty code_seq -code_seq code_seq_empty() -{ - code_seq ret; - ret.first = NULL; - ret.last = NULL; - code_seq_okay(ret); - return ret; -} - -// Requires: c != NULL -// Return a code_seq containing just the given code -code_seq code_seq_singleton(code *c) -{ - code_seq ret; - ret.first = c; - ret.last = c; - code_seq_okay(ret); - return ret; -} - -// Is seq empty? -bool code_seq_is_empty(code_seq seq) -{ - code_seq_okay(seq); - return seq.first == NULL; -} - -// Requires: !code_seq_is_empty(seq) -// Return the first element of the given code sequence, seq -code *code_seq_first(code_seq seq) -{ - assert(!code_seq_is_empty(seq)); - return seq.first; -} - -// Requires: !code_seq_is_empty(seq) -// Return a new code_seq containing -// the rest of the given sequence, seq -// Note that seq is not modified -code_seq code_seq_rest(code_seq seq) -{ - assert(!code_seq_is_empty(seq)); - code *first = seq.first; - code_seq ret; - ret.first = first->next; - if (ret.first == NULL) { - ret.last = NULL; - } else { - ret.last = seq.last; - } - code_seq_okay(ret); - return ret; -} - -// Return the size (number of instructions/words) in seq -unsigned int code_seq_size(code_seq seq) -{ - unsigned int ret = 0; - while (!code_seq_is_empty(seq)) { - ret++; - seq = code_seq_rest(seq); - } - return ret; -} - -// Requires: !code_seq_is_empty(seq) -// Return the last element in the given sequence -code *code_seq_last_elem(code_seq seq) -{ - assert(!code_seq_is_empty(seq)); - return seq.last; -} - -// Requires: c != NULL && seq != NULL -// Modify seq to add the given code *c added to its end -void code_seq_add_to_end(code_seq *seq, code *c) -{ - assert(c != NULL); - if (code_seq_is_empty(*seq)) { - seq->first = c; - seq->last = c; - } else { - // assert(!code_seq_is_empty(seq)); - code *last = code_seq_last_elem(*seq); - last->next = c; - c->next = NULL; - seq->last = c; - } - code_seq_okay(*seq); -} - -// Requires: s1 != NULL && s2 != NULL -// Modifies s1 to be the concatenation of s1 followed by s2 -void code_seq_concat(code_seq *s1, code_seq s2) -{ - if (code_seq_is_empty(*s1)) { - s1->first = s2.first; - s1->last = s2.last; - } else if (code_seq_is_empty(s2)) { - ; // s1 is already their concatenation - } else { - code *last = code_seq_last_elem(*s1); - // assert(last != NULL); - last->next = s2.first; - s1->last = s2.last; - } - code_seq_okay(*s1); -} - -// Requires: out is open for writing. -// Print the instructions in the code_seq to out -// in assembly language format -void code_seq_debug_print(FILE *out, code_seq seq) -{ - while(!code_seq_is_empty(seq)) { - fprintf(out, "%s\n", - instruction_assembly_form(0, code_seq_first(seq)->instr)); - seq = code_seq_rest(seq); - } -} +/* $Id: code_seq.c,v 1.4 2024/11/08 21:01:43 leavens Exp $ */ +#include +#include +#include +#include "utilities.h" +#include "regname.h" +#include "code.h" +#include "code_seq.h" + + +static void code_seq_okay(code_seq seq) +{ + // seq.first and seq.last are either both null or both not null + assert((seq.first == NULL) == (seq.last == NULL)); +} + +// Return an empty code_seq +code_seq code_seq_empty() +{ + code_seq ret; + ret.first = NULL; + ret.last = NULL; + code_seq_okay(ret); + return ret; +} + +// Requires: c != NULL +// Return a code_seq containing just the given code +code_seq code_seq_singleton(code *c) +{ + code_seq ret; + ret.first = c; + ret.last = c; + code_seq_okay(ret); + return ret; +} + +// Is seq empty? +bool code_seq_is_empty(code_seq seq) +{ + code_seq_okay(seq); + return seq.first == NULL; +} + +// Requires: !code_seq_is_empty(seq) +// Return the first element of the given code sequence, seq +code *code_seq_first(code_seq seq) +{ + assert(!code_seq_is_empty(seq)); + return seq.first; +} + +// Requires: !code_seq_is_empty(seq) +// Return a new code_seq containing +// the rest of the given sequence, seq +// Note that seq is not modified +code_seq code_seq_rest(code_seq seq) +{ + assert(!code_seq_is_empty(seq)); + code *first = seq.first; + code_seq ret; + ret.first = first->next; + if (ret.first == NULL) { + ret.last = NULL; + } else { + ret.last = seq.last; + } + code_seq_okay(ret); + return ret; +} + +// Return the size (number of instructions/words) in seq +unsigned int code_seq_size(code_seq seq) +{ + unsigned int ret = 0; + while (!code_seq_is_empty(seq)) { + ret++; + seq = code_seq_rest(seq); + } + return ret; +} + +// Requires: !code_seq_is_empty(seq) +// Return the last element in the given sequence +code *code_seq_last_elem(code_seq seq) +{ + assert(!code_seq_is_empty(seq)); + return seq.last; +} + +// Requires: c != NULL && seq != NULL +// Modify seq to add the given code *c added to its end +void code_seq_add_to_end(code_seq *seq, code *c) +{ + assert(c != NULL); + if (code_seq_is_empty(*seq)) { + seq->first = c; + seq->last = c; + } else { + // assert(!code_seq_is_empty(seq)); + code *last = code_seq_last_elem(*seq); + last->next = c; + c->next = NULL; + seq->last = c; + } + code_seq_okay(*seq); +} + +// Requires: s1 != NULL && s2 != NULL +// Modifies s1 to be the concatenation of s1 followed by s2 +void code_seq_concat(code_seq *s1, code_seq s2) +{ + if (code_seq_is_empty(*s1)) { + s1->first = s2.first; + s1->last = s2.last; + } else if (code_seq_is_empty(s2)) { + ; // s1 is already their concatenation + } else { + code *last = code_seq_last_elem(*s1); + // assert(last != NULL); + last->next = s2.first; + s1->last = s2.last; + } + code_seq_okay(*s1); +} + +// Requires: out is open for writing. +// Print the instructions in the code_seq to out +// in assembly language format +void code_seq_debug_print(FILE *out, code_seq seq) +{ + while(!code_seq_is_empty(seq)) { + fprintf(out, "%s\n", + instruction_assembly_form(0, code_seq_first(seq)->instr)); + seq = code_seq_rest(seq); + } +} diff --git a/code_seq.h b/FromGithub/code_seq.h old mode 100755 new mode 100644 similarity index 92% rename from code_seq.h rename to FromGithub/code_seq.h index 830cffe..0232eb9 --- a/code_seq.h +++ b/FromGithub/code_seq.h @@ -1,53 +1,56 @@ -/* $Id: code_seq.h,v 1.3 2024/11/08 21:01:43 leavens Exp $ */ -#ifndef _CODE_SEQ_H -#define _CODE_SEQ_H -#include -#include "code.h" - -// code sequences are linked lists -// with an additional last pointer to the last node -typedef struct { - code *first; - code *last; -} code_seq; - -// Return an empty code_seq -extern code_seq code_seq_empty(); - -// Return a code_seq containing just the given code -extern code_seq code_seq_singleton(code *c); - -// Is seq empty? -extern bool code_seq_is_empty(code_seq seq); - -// Requires: !code_seq_is_empty(seq) -// Return the first element of the given code sequence, seq -extern code *code_seq_first(code_seq seq); - -// Requires: !code_seq_is_empty(seq) -// Return a new code_seq containing -// the rest of the given sequence, seq -// Note that seq is not modified -extern code_seq code_seq_rest(code_seq seq); - -// Return the size (number of instructions/words) in seq -extern unsigned int code_seq_size(code_seq seq); - -// Requires: !code_seq_is_empty(seq) -// Return the last element in the given sequence -extern code *code_seq_last_elem(code_seq seq); - -// Requires: c != NULL && seq != NULL -// Modify seq to add the given code *c added to its end -extern void code_seq_add_to_end(code_seq *seq, code *c); - -// Requires: s1 != NULL && s2 != NULL -// Modifies s1 to be the concatenation of s1 followed by s2 -extern void code_seq_concat(code_seq *s1, code_seq s2); - -// Requires: out is open for writing. -// Print the instructions in the code_seq to out -// in assembly language format -extern void code_seq_debug_print(FILE *out, code_seq seq); - -#endif +/* $Id: code_seq.h,v 1.3 2024/11/08 21:01:43 leavens Exp $ */ +#ifndef _CODE_SEQ_H +#define _CODE_SEQ_H +#include + +// Forward declare 'code' type to avoid circular dependency +struct code_s; +typedef struct code_s code; // Declare code as a type + +// code sequences are linked lists +// with an additional last pointer to the last node +typedef struct { + code *first; + code *last; +} code_seq; + +// Return an empty code_seq +extern code_seq code_seq_empty(); + +// Return a code_seq containing just the given code +extern code_seq code_seq_singleton(code *c); + +// Is seq empty? +extern bool code_seq_is_empty(code_seq seq); + +// Requires: !code_seq_is_empty(seq) +// Return the first element of the given code sequence, seq +extern code *code_seq_first(code_seq seq); + +// Requires: !code_seq_is_empty(seq) +// Return a new code_seq containing +// the rest of the given sequence, seq +// Note that seq is not modified +extern code_seq code_seq_rest(code_seq seq); + +// Return the size (number of instructions/words) in seq +extern unsigned int code_seq_size(code_seq seq); + +// Requires: !code_seq_is_empty(seq) +// Return the last element in the given sequence +extern code *code_seq_last_elem(code_seq seq); + +// Requires: c != NULL && seq != NULL +// Modify seq to add the given code *c added to its end +extern void code_seq_add_to_end(code_seq *seq, code *c); + +// Requires: s1 != NULL && s2 != NULL +// Modifies s1 to be the concatenation of s1 followed by s2 +extern void code_seq_concat(code_seq *s1, code_seq s2); + +// Requires: out is open for writing. +// Print the instructions in the code_seq to out +// in assembly language format +extern void code_seq_debug_print(FILE *out, code_seq seq); + +#endif diff --git a/FromGithub/code_seq.o b/FromGithub/code_seq.o new file mode 100644 index 0000000..59cb0cc Binary files /dev/null and b/FromGithub/code_seq.o differ diff --git a/code_utils.c b/FromGithub/code_utils.c old mode 100755 new mode 100644 similarity index 97% rename from code_utils.c rename to FromGithub/code_utils.c index d5c0eed..8b54474 --- a/code_utils.c +++ b/FromGithub/code_utils.c @@ -1,158 +1,158 @@ -// $Id: code_utils.c,v 1.8 2024/11/11 23:01:08 leavens Exp $ -#include -#include "regname.h" -#include "code.h" -#include "code_seq.h" -#include "code_utils.h" - -#define MINIMAL_STACK_ALLOC_IN_WORDS 4 -#define SAVED_SP_OFFSET (-1) -#define SAVED_FP_OFFSET (-2) -#define SAVED_STATIC_LINK_OFFSET (-3) -#define SAVED_RA_OFFSET (-4) - -// Requires: t != SP && s != SP -// Return a code sequence that copies the value from register s -// into register t, using the top of the stack as a temporary. -// Modifies: t (and temporarily, SP) -code_seq code_utils_copy_regs(reg_num_type t, reg_num_type s) -{ - assert(t != SP); - assert(s != SP); - code_seq ret = code_seq_singleton(code_cpr(t, s)); - // If the SSM didn't have the cpr instruction - // one could use the top of the stack as a temporary, as follows - /* - code_seq ret = code_utils_allocate_stack_space(1); - code_seq_add_to_end(&ret, code_swr(SP, 0, s)); - code_seq_add_to_end(&ret, code_lwr(t, SP, 0)); - code_seq_concat(&ret, code_utils_deallocate_stack_space(1)); - */ - return ret; -} - -// Return a code sequence that loads the static link -// (which is SAVEDSTATIC_LINK_OFFSET from the address contained in register b, -// and place it in register rt. -// Modifies only register rt. -code_seq code_utils_load_static_link_into_reg(reg_num_type t, - reg_num_type b) -{ - code_seq ret = code_seq_singleton(code_lwr(t, b, SAVED_STATIC_LINK_OFFSET)); - return ret; -} - -// Requires: reg != FP && reg != RA -// Modifies only: register reg -// Return a code sequence that will put the address that corresponds to the -// frame pointer for the given number of scopes outward in register reg -code_seq code_utils_compute_fp(reg_num_type reg, unsigned int levelsOut) -{ - assert(reg != FP && reg != RA); - code_seq ret - = code_utils_copy_regs(reg, FP); - while (levelsOut > 0) { - code_seq_concat(&ret, - code_utils_load_static_link_into_reg(reg, reg)); - levelsOut--; - } - return ret; -} - -// Requires: words >= 0 -// Allocate the given number of words on the runtime stack -// Modifies when executed: SP register -// At the end of exeuction, SP holds the address of the last allocated word. -// (So, if the call allocates only one word, then SP addresses that word.) -code_seq code_utils_allocate_stack_space(immediate_type words) -{ - assert(words >= 0); - code_seq ret = code_seq_singleton(code_sri(SP, words)); - return ret; -} - -// Requires: words >= 0 -// Deallocate the given number of words from the runtime stack -// Modifies when executed: SP register -code_seq code_utils_deallocate_stack_space(immediate_type words) -{ - assert(words >= 0); - code_seq ret = code_seq_singleton(code_ari(SP, words)); - return ret; -} - -// Requires: $r3 holds the static link (from the current AR) -// Set up the runtime stack for a procedure, -// where the static link is found in register $r3. -// Modifies when executed, the SP register, the FP register, -// and memory from SP to SP - MINIMAL_STACK_ALLOC_IN_WORDS -// (inclusive) -code_seq code_utils_save_registers_for_AR() -{ - // assume that SP is pointing to the lowest local storage already allocated - code_seq ret; - // save SP onto the top of the stack - ret = code_seq_singleton(code_swr(SP, SAVED_SP_OFFSET, SP)); - // save FP (dynamic link) onto top of the stack - code_seq_add_to_end(&ret, code_swr(SP, SAVED_FP_OFFSET, FP)); - // save the static link from $r3 onto top of stack - code_seq_add_to_end(&ret, code_swr(SP, SAVED_STATIC_LINK_OFFSET, 3)); - // save the RA register on the stack - code_seq_add_to_end(&ret, code_swr(SP, SAVED_RA_OFFSET, RA)); - // save SP into the FP register so FP points to the base of the AR - // can't use code_utils_copy_regs for this because SP is involved - code_seq_add_to_end(&ret, code_cpr(FP, SP)); - /* the following can be used if there is no cpr instruction: - code_seq_add_to_end(&ret, SAVED_RA_OFFSET-1, SP)); - code_seq_add_to_end(&ret, code_lwr(FP, SP, SAVED_RA_OFFSET-1)); - */ - - // allocate the space on the stack for the saved registers - code_seq_concat(&ret, - code_utils_allocate_stack_space(MINIMAL_STACK_ALLOC_IN_WORDS)); - - return ret; -} - -// Restore the callee's registers from the places they are saved on the stack. -// This restores the SP, FP, and RA registers only. -// (It is assumed that the stack already holds the static link address) -// Modifies when executed, the SP register, the FP register, the RA register. -// restoring their saved contents from memory -// (as saved by code_utils_save_registers_for_AR) -code_seq code_utils_restore_registers_from_AR() -{ - code_seq ret = code_seq_empty(); - // restore the RA register - code_seq_add_to_end(&ret, - code_lwr(RA, FP, SAVED_RA_OFFSET)); - // save the SP register in $r3 temporarily, to not violate VM's invariant - code_seq_add_to_end(&ret, code_lwr(3, FP, SAVED_SP_OFFSET)); - // restore the FP (dynamic link) register - code_seq_add_to_end(&ret, code_lwr(FP, FP, SAVED_FP_OFFSET)); - // deallocate the space for variables and constants by restoring old SP - code_seq_add_to_end(&ret, code_cpr(SP, 3)); - return ret; -} - -// Set up the program's stack as if it were in a call (from the OS) -code_seq code_utils_set_up_program() -{ - code_seq ret; - // set up the saved registers - ret = code_utils_copy_regs(3, FP); // save FP into $r3 - code_seq_concat(&ret, code_utils_save_registers_for_AR()); - // use what will be the new FP as the saved static link - code_seq_add_to_end(&ret, code_swr(FP, SAVED_STATIC_LINK_OFFSET, FP)); - return ret; -} - -// Tear down the program's stack and exit (with exit code 0). -code_seq code_utils_tear_down_program() -{ - code_seq ret; - // restore the saved registers to their initial state - ret = code_utils_restore_registers_from_AR(); - code_seq_add_to_end(&ret, code_exit(0)); - return ret; -} +// $Id: code_utils.c,v 1.8 2024/11/11 23:01:08 leavens Exp $ +#include +#include "regname.h" +#include "code.h" +#include "code_seq.h" +#include "code_utils.h" + +#define MINIMAL_STACK_ALLOC_IN_WORDS 4 +#define SAVED_SP_OFFSET (-1) +#define SAVED_FP_OFFSET (-2) +#define SAVED_STATIC_LINK_OFFSET (-3) +#define SAVED_RA_OFFSET (-4) + +// Requires: t != SP && s != SP +// Return a code sequence that copies the value from register s +// into register t, using the top of the stack as a temporary. +// Modifies: t (and temporarily, SP) +code_seq code_utils_copy_regs(reg_num_type t, reg_num_type s) +{ + assert(t != SP); + assert(s != SP); + code_seq ret = code_seq_singleton(code_cpr(t, s)); + // If the SSM didn't have the cpr instruction + // one could use the top of the stack as a temporary, as follows + /* + code_seq ret = code_utils_allocate_stack_space(1); + code_seq_add_to_end(&ret, code_swr(SP, 0, s)); + code_seq_add_to_end(&ret, code_lwr(t, SP, 0)); + code_seq_concat(&ret, code_utils_deallocate_stack_space(1)); + */ + return ret; +} + +// Return a code sequence that loads the static link +// (which is SAVEDSTATIC_LINK_OFFSET from the address contained in register b, +// and place it in register rt. +// Modifies only register rt. +code_seq code_utils_load_static_link_into_reg(reg_num_type t, + reg_num_type b) +{ + code_seq ret = code_seq_singleton(code_lwr(t, b, SAVED_STATIC_LINK_OFFSET)); + return ret; +} + +// Requires: reg != FP && reg != RA +// Modifies only: register reg +// Return a code sequence that will put the address that corresponds to the +// frame pointer for the given number of scopes outward in register reg +code_seq code_utils_compute_fp(reg_num_type reg, unsigned int levelsOut) +{ + assert(reg != FP && reg != RA); + code_seq ret + = code_utils_copy_regs(reg, FP); + while (levelsOut > 0) { + code_seq_concat(&ret, + code_utils_load_static_link_into_reg(reg, reg)); + levelsOut--; + } + return ret; +} + +// Requires: words >= 0 +// Allocate the given number of words on the runtime stack +// Modifies when executed: SP register +// At the end of exeuction, SP holds the address of the last allocated word. +// (So, if the call allocates only one word, then SP addresses that word.) +code_seq code_utils_allocate_stack_space(immediate_type words) +{ + assert(words >= 0); + code_seq ret = code_seq_singleton(code_sri(SP, words)); + return ret; +} + +// Requires: words >= 0 +// Deallocate the given number of words from the runtime stack +// Modifies when executed: SP register +code_seq code_utils_deallocate_stack_space(immediate_type words) +{ + assert(words >= 0); + code_seq ret = code_seq_singleton(code_ari(SP, words)); + return ret; +} + +// Requires: $r3 holds the static link (from the current AR) +// Set up the runtime stack for a procedure, +// where the static link is found in register $r3. +// Modifies when executed, the SP register, the FP register, +// and memory from SP to SP - MINIMAL_STACK_ALLOC_IN_WORDS +// (inclusive) +code_seq code_utils_save_registers_for_AR() +{ + // assume that SP is pointing to the lowest local storage already allocated + code_seq ret; + // save SP onto the top of the stack + ret = code_seq_singleton(code_swr(SP, SAVED_SP_OFFSET, SP)); + // save FP (dynamic link) onto top of the stack + code_seq_add_to_end(&ret, code_swr(SP, SAVED_FP_OFFSET, FP)); + // save the static link from $r3 onto top of stack + code_seq_add_to_end(&ret, code_swr(SP, SAVED_STATIC_LINK_OFFSET, 3)); + // save the RA register on the stack + code_seq_add_to_end(&ret, code_swr(SP, SAVED_RA_OFFSET, RA)); + // save SP into the FP register so FP points to the base of the AR + // can't use code_utils_copy_regs for this because SP is involved + code_seq_add_to_end(&ret, code_cpr(FP, SP)); + /* the following can be used if there is no cpr instruction: + code_seq_add_to_end(&ret, SAVED_RA_OFFSET-1, SP)); + code_seq_add_to_end(&ret, code_lwr(FP, SP, SAVED_RA_OFFSET-1)); + */ + + // allocate the space on the stack for the saved registers + code_seq_concat(&ret, + code_utils_allocate_stack_space(MINIMAL_STACK_ALLOC_IN_WORDS)); + + return ret; +} + +// Restore the callee's registers from the places they are saved on the stack. +// This restores the SP, FP, and RA registers only. +// (It is assumed that the stack already holds the static link address) +// Modifies when executed, the SP register, the FP register, the RA register. +// restoring their saved contents from memory +// (as saved by code_utils_save_registers_for_AR) +code_seq code_utils_restore_registers_from_AR() +{ + code_seq ret = code_seq_empty(); + // restore the RA register + code_seq_add_to_end(&ret, + code_lwr(RA, FP, SAVED_RA_OFFSET)); + // save the SP register in $r3 temporarily, to not violate VM's invariant + code_seq_add_to_end(&ret, code_lwr(3, FP, SAVED_SP_OFFSET)); + // restore the FP (dynamic link) register + code_seq_add_to_end(&ret, code_lwr(FP, FP, SAVED_FP_OFFSET)); + // deallocate the space for variables and constants by restoring old SP + code_seq_add_to_end(&ret, code_cpr(SP, 3)); + return ret; +} + +// Set up the program's stack as if it were in a call (from the OS) +code_seq code_utils_set_up_program() +{ + code_seq ret; + // set up the saved registers + ret = code_utils_copy_regs(3, FP); // save FP into $r3 + code_seq_concat(&ret, code_utils_save_registers_for_AR()); + // use what will be the new FP as the saved static link + code_seq_add_to_end(&ret, code_swr(FP, SAVED_STATIC_LINK_OFFSET, FP)); + return ret; +} + +// Tear down the program's stack and exit (with exit code 0). +code_seq code_utils_tear_down_program() +{ + code_seq ret; + // restore the saved registers to their initial state + ret = code_utils_restore_registers_from_AR(); + code_seq_add_to_end(&ret, code_exit(0)); + return ret; +} diff --git a/code_utils.h b/FromGithub/code_utils.h old mode 100755 new mode 100644 similarity index 97% rename from code_utils.h rename to FromGithub/code_utils.h index d81da30..6bf4259 --- a/code_utils.h +++ b/FromGithub/code_utils.h @@ -1,59 +1,59 @@ -// $Id: code_utils.h,v 1.4 2024/11/10 22:06:54 leavens Exp $ -// Some convenience functions that may help with code generation -#ifndef _CODE_UTILS_H -#define _CODE_UTILS_H -#include "code_seq.h" - -// Requires: t != SP && s != SP -// Return a code sequence that copies the value from register s -// into register t, using the top of the stack as a temporary. -// Modifies: t (and temporarily, SP) -extern code_seq code_utils_copy_regs(reg_num_type t, reg_num_type s); - -// Return a code sequence that loads the static link -// (which is SAVEDSTATIC_LINK_OFFSET from the address contained in register b, -// and place it in register rt. -// Modifies only register rt. -extern code_seq code_utils_load_static_link_into_reg(reg_num_type t, - reg_num_type b); - -// Requires: reg != FP && reg != RA -// Modifies only: register reg -// Return a code sequence that will put the address that corresponds to the -// frame pointer for the given number of scopes outward in register reg -extern code_seq code_utils_compute_fp(reg_num_type reg, unsigned int levelsOut); - -// Requires: words >= 0 -// Allocate the given number of words on the runtime stack -// Modifies when executed: SP register -// At the end of exeuction, SP holds the address of the last allocated word. -// (So, if the call allocates only one word, then SP addresses that word.) -extern code_seq code_utils_allocate_stack_space(immediate_type words); - -// Requires: words >= 0 -// Deallocate the given number of words from the runtime stack -// Modifies when executed: SP register -extern code_seq code_utils_deallocate_stack_space(immediate_type words); - -// Set up the runtime stack for a procedure, -// where the static link is found in register $r3. -// Modifies when executed, the SP register, the FP register, -// and memory from SP to SP - MINIMAL_STACK_ALLOC_IN_WORDS -// (inclusive) -extern code_seq code_utils_save_registers_for_AR(); - -// Restore the callee's registers from the places they are saved on the stack. -// This restores the SP, FP, and RA registers only. -// (It is assumed that the stack already holds the static link address) -// Modifies when executed, the SP register, the FP register, the RA register. -// restoring their saved contents from memory -// (as saved by code_utils_save_registers_for_AR) -extern code_seq code_utils_restore_registers_from_AR(); - -// Set up the program's stack as if it were in a call (from the OS) -extern code_seq code_utils_set_up_program(); - -// Tear down the program's stack and exit (with exit code 0). -extern code_seq code_utils_tear_down_program(); - -#endif +// $Id: code_utils.h,v 1.4 2024/11/10 22:06:54 leavens Exp $ +// Some convenience functions that may help with code generation +#ifndef _CODE_UTILS_H +#define _CODE_UTILS_H +#include "code_seq.h" + +// Requires: t != SP && s != SP +// Return a code sequence that copies the value from register s +// into register t, using the top of the stack as a temporary. +// Modifies: t (and temporarily, SP) +extern code_seq code_utils_copy_regs(reg_num_type t, reg_num_type s); + +// Return a code sequence that loads the static link +// (which is SAVEDSTATIC_LINK_OFFSET from the address contained in register b, +// and place it in register rt. +// Modifies only register rt. +extern code_seq code_utils_load_static_link_into_reg(reg_num_type t, + reg_num_type b); + +// Requires: reg != FP && reg != RA +// Modifies only: register reg +// Return a code sequence that will put the address that corresponds to the +// frame pointer for the given number of scopes outward in register reg +extern code_seq code_utils_compute_fp(reg_num_type reg, unsigned int levelsOut); + +// Requires: words >= 0 +// Allocate the given number of words on the runtime stack +// Modifies when executed: SP register +// At the end of exeuction, SP holds the address of the last allocated word. +// (So, if the call allocates only one word, then SP addresses that word.) +extern code_seq code_utils_allocate_stack_space(immediate_type words); + +// Requires: words >= 0 +// Deallocate the given number of words from the runtime stack +// Modifies when executed: SP register +extern code_seq code_utils_deallocate_stack_space(immediate_type words); + +// Set up the runtime stack for a procedure, +// where the static link is found in register $r3. +// Modifies when executed, the SP register, the FP register, +// and memory from SP to SP - MINIMAL_STACK_ALLOC_IN_WORDS +// (inclusive) +extern code_seq code_utils_save_registers_for_AR(); + +// Restore the callee's registers from the places they are saved on the stack. +// This restores the SP, FP, and RA registers only. +// (It is assumed that the stack already holds the static link address) +// Modifies when executed, the SP register, the FP register, the RA register. +// restoring their saved contents from memory +// (as saved by code_utils_save_registers_for_AR) +extern code_seq code_utils_restore_registers_from_AR(); + +// Set up the program's stack as if it were in a call (from the OS) +extern code_seq code_utils_set_up_program(); + +// Tear down the program's stack and exit (with exit code 0). +extern code_seq code_utils_tear_down_program(); + +#endif diff --git a/FromGithub/code_utils.o b/FromGithub/code_utils.o new file mode 100644 index 0000000..aea3243 Binary files /dev/null and b/FromGithub/code_utils.o differ diff --git a/compiler_main.c b/FromGithub/compiler_main.c old mode 100755 new mode 100644 similarity index 57% rename from compiler_main.c rename to FromGithub/compiler_main.c index bb1c25a..4310e48 --- a/compiler_main.c +++ b/FromGithub/compiler_main.c @@ -1,120 +1,120 @@ -/* $Id: compiler_main.c,v 1.18 2024/11/13 20:33:01 leavens Exp $ */ -#include -#include -#include -#include "bof.h" -#include "lexer.h" -#include "parser.h" -#include "unparser.h" -#include "ast.h" -#include "utilities.h" -#include "symtab.h" -#include "scope_check.h" -#include "gen_code.h" - -/* Print a usage message on stderr - and exit with failure. */ -static void usage(const char *cmdname) -{ - fprintf(stderr, "Usage: %s %s\n %s %s\n %s %s\n", - cmdname, "-l codeFilename.spl", - cmdname, "-u codeFilename.spl", - cmdname, " codeFilename.spl"); - exit(EXIT_FAILURE); -} - -// If the -l option is used, then output the tokens -// in the give file name to stdout, -// otherwise unparse the program given in the file name argument to stdout -int main(int argc, char *argv[]) -{ - // should the lexer's tokens be shown? - bool lexer_print_output = false; - // should the unparse of the AST be shown? - bool parser_unparse = false; - const char *cmdname = argv[0]; - argc--; - argv++; - // possible options: -l, and -u - while (argc > 0 && strlen(argv[0]) >= 2 && argv[0][0] == '-') - { - if (strcmp(argv[0], "-l") == 0) - { - lexer_print_output = true; - argc--; - argv++; - } - else if (strcmp(argv[0], "-u") == 0) - { - parser_unparse = true; - argc--; - argv++; - } - else - { - // bad option! - usage(cmdname); - } - } - - // give usage message if -l and other options are used - if (lexer_print_output && parser_unparse) - { - usage(cmdname); - } - - // must have a file name - if (argc <= 0 || (strlen(argv[0]) >= 2 && argv[0][0] == '-')) - { - usage(cmdname); - } - - // the name of the file - char *filename = argv[0]; - char *lastdot = strrchr(filename, '.'); - if (lastdot == NULL || strcmp(lastdot, ".spl") != 0) - { - bail_with_error("filename argument must end in .spl not %s", - filename); - } - char boffilename[BUFSIZ]; - strncpy(boffilename, filename, BUFSIZ); - int len = strlen(boffilename); - assert(len < BUFSIZ); // it has to fit! - strncpy(boffilename + (len - 4), ".bof", 5); - // debug_print("Output going to %s\n", boffilename); - - if (lexer_print_output) - { - // with the lexer_print_output option, nothing else is done - lexer_init(filename); - lexer_output(); - return EXIT_SUCCESS; - } - - // otherwise (if not lexer_print_outout) continue to parse etc. - block_t progast = parseProgram(filename); - - if (parser_unparse) - { - unparseProgram(stdout, progast); - } - - // build symbol table and... - symtab_initialize(); - // check for duplicate declarations - // and record id-use information in the AST - scope_check_program(&progast); - - if (parser_unparse) - { - return EXIT_SUCCESS; - } - - // generate code from the ASTs - gen_code_initialize(); - BOFFILE bf = bof_write_open(boffilename); - gen_code_program(bf, progast); - - return EXIT_SUCCESS; -} +/* $Id: compiler_main.c,v 1.18 2024/11/13 20:33:01 leavens Exp $ */ +#include +#include +#include +#include "bof.h" +#include "lexer.h" +#include "parser.h" +#include "unparser.h" +#include "ast.h" +#include "utilities.h" +#include "symtab.h" +#include "scope_check.h" + +// The functions gen_code_initialize and gen_code_program +// would normally be declared in gen_code.h, +// but part of the homework is to write that gen_code module, +// so they are declared below to make this file self-contained. + +// Initialize the code generator +extern void gen_code_initialize(); + +// Requires: bf is open for writing +// Generate code for prog into bf +extern void gen_code_program(BOFFILE bf, block_t prog); + +/* Print a usage message on stderr + and exit with failure. */ +static void usage(const char *cmdname) +{ + fprintf(stderr, "Usage: %s %s\n %s %s\n %s %s\n", + cmdname, "-l codeFilename.spl", + cmdname, "-u codeFilename.spl", + cmdname, " codeFilename.spl" + ); + exit(EXIT_FAILURE); +} + +// If the -l option is used, then output the tokens +// in the give file name to stdout, +// otherwise unparse the program given in the file name argument to stdout +int main(int argc, char *argv[]) +{ + // should the lexer's tokens be shown? + bool lexer_print_output = false; + // should the unparse of the AST be shown? + bool parser_unparse = false; + const char *cmdname = argv[0]; + argc--; + argv++; + // possible options: -l, and -u + while (argc > 0 && strlen(argv[0]) >= 2 && argv[0][0] == '-') { + if (strcmp(argv[0],"-l") == 0) { + lexer_print_output = true; + argc--; + argv++; + } else if (strcmp(argv[0],"-u") == 0) { + parser_unparse = true; + argc--; + argv++; + } else { + // bad option! + usage(cmdname); + } + } + + // give usage message if -l and other options are used + if (lexer_print_output && parser_unparse) { + usage(cmdname); + } + + // must have a file name + if (argc <= 0 || (strlen(argv[0]) >= 2 && argv[0][0] == '-')) { + usage(cmdname); + } + + // the name of the file + char *filename = argv[0]; + char *lastdot = strrchr(filename, '.'); + if (lastdot == NULL || strcmp(lastdot, ".spl") != 0) { + bail_with_error("filename argument must end in .spl not %s", + filename); + } + char boffilename[BUFSIZ]; + strncpy(boffilename, filename, BUFSIZ); + int len = strlen(boffilename); + assert(len < BUFSIZ); // it has to fit! + strncpy(boffilename+(len-4), ".bof", 5); + // debug_print("Output going to %s\n", boffilename); + + if (lexer_print_output) { + // with the lexer_print_output option, nothing else is done + lexer_init(filename); + lexer_output(); + return EXIT_SUCCESS; + } + + // otherwise (if not lexer_print_outout) continue to parse etc. + block_t progast = parseProgram(filename); + + if (parser_unparse) { + unparseProgram(stdout, progast); + } + + // build symbol table and... + symtab_initialize(); + // check for duplicate declarations + // and record id-use information in the AST + scope_check_program(&progast); + + if (parser_unparse) { + return EXIT_SUCCESS; + } + + // generate code from the ASTs + gen_code_initialize(); + BOFFILE bf = bof_write_open(boffilename); + gen_code_program(bf, progast); + + return EXIT_SUCCESS; +} diff --git a/FromGithub/compiler_main.o b/FromGithub/compiler_main.o new file mode 100644 index 0000000..b165041 Binary files /dev/null and b/FromGithub/compiler_main.o differ diff --git a/file_location.c b/FromGithub/file_location.c old mode 100755 new mode 100644 similarity index 96% rename from file_location.c rename to FromGithub/file_location.c index c7ceae7..f6938c8 --- a/file_location.c +++ b/FromGithub/file_location.c @@ -1,34 +1,34 @@ -/* $Id: file_location.c,v 1.2 2023/11/13 05:13:47 leavens Exp $ */ -#include -#include -#include -#include "file_location.h" -#include "utilities.h" - -// Requires: filename != NULL -// Return a (pointer to a) fresh file_location with the given -// information -file_location *file_location_make(const char *filename, - unsigned int line) -{ - file_location *ret = (file_location *) malloc(sizeof(file_location)); - if (ret == NULL) { - bail_with_error("Could not allocate space for a file_location!"); - } - ret->filename = filename; - ret->line = line; - return ret; -} - -// Requires: fl != NULL -// Return a (pointer to a) fresh copy of fl -file_location *file_location_copy(file_location *fl) -{ - file_location *ret = (file_location *) malloc(sizeof(file_location)); - if (ret == NULL) { - bail_with_error("Could not allocate space for a file_location!"); - } - ret->filename = fl->filename; - ret->line = fl->line; - return ret; -} +/* $Id: file_location.c,v 1.2 2023/11/13 05:13:47 leavens Exp $ */ +#include +#include +#include +#include "file_location.h" +#include "utilities.h" + +// Requires: filename != NULL +// Return a (pointer to a) fresh file_location with the given +// information +file_location *file_location_make(const char *filename, + unsigned int line) +{ + file_location *ret = (file_location *) malloc(sizeof(file_location)); + if (ret == NULL) { + bail_with_error("Could not allocate space for a file_location!"); + } + ret->filename = filename; + ret->line = line; + return ret; +} + +// Requires: fl != NULL +// Return a (pointer to a) fresh copy of fl +file_location *file_location_copy(file_location *fl) +{ + file_location *ret = (file_location *) malloc(sizeof(file_location)); + if (ret == NULL) { + bail_with_error("Could not allocate space for a file_location!"); + } + ret->filename = fl->filename; + ret->line = fl->line; + return ret; +} diff --git a/file_location.h b/FromGithub/file_location.h old mode 100755 new mode 100644 similarity index 96% rename from file_location.h rename to FromGithub/file_location.h index 19d1931..603b398 --- a/file_location.h +++ b/FromGithub/file_location.h @@ -1,21 +1,21 @@ -/* $Id: file_location.h,v 1.2 2023/11/13 05:13:48 leavens Exp $ */ -#ifndef _FILE_LOCATION_H -#define _FILE_LOCATION_H - -// location in a source file (useful for error messages) -typedef struct { - const char *filename; - unsigned int line; // of first token -} file_location; - -// Requires: filename != NULL -// Return a (pointer to a) fresh file_location with the given -// information -extern file_location *file_location_make(const char *filename, - unsigned int line); - -// Requires: fl != NULL -// Return a (pointer to a) fresh copy of fl -extern file_location *file_location_copy(file_location *fl); - -#endif +/* $Id: file_location.h,v 1.2 2023/11/13 05:13:48 leavens Exp $ */ +#ifndef _FILE_LOCATION_H +#define _FILE_LOCATION_H + +// location in a source file (useful for error messages) +typedef struct { + const char *filename; + unsigned int line; // of first token +} file_location; + +// Requires: filename != NULL +// Return a (pointer to a) fresh file_location with the given +// information +extern file_location *file_location_make(const char *filename, + unsigned int line); + +// Requires: fl != NULL +// Return a (pointer to a) fresh copy of fl +extern file_location *file_location_copy(file_location *fl); + +#endif diff --git a/FromGithub/file_location.o b/FromGithub/file_location.o new file mode 100644 index 0000000..e39fffd Binary files /dev/null and b/FromGithub/file_location.o differ diff --git a/gen_code.c b/FromGithub/gen_code.c similarity index 80% rename from gen_code.c rename to FromGithub/gen_code.c index ea359d7..60b5162 100644 --- a/gen_code.c +++ b/FromGithub/gen_code.c @@ -90,34 +90,35 @@ void gen_code_program(BOFFILE bf, block_t prog) code_seq main_cs; // We want to make the main program's AR look like all blocks... so: // allocate space and initialize any variables - main_cs = gen_code_var_decls(prog.var_decls); - int vars_len_in_bytes = (code_seq_size(main_cs) / 2) * BYTES_PER_WORD; + main_cs = gen_code_seq_var_decls(prog.var_decls);//gen_code_seq_var_decls’ + //int vars_len_in_bytes = (code_seq_size(main_cs) / 2) * BYTES_PER_WORD; variable that has been muted based on line 101-104 // there is no static link for the program as a whole, // so nothing to do for saving FP into A0 as would be done for a block - code_seq_concat(main_cs, code_save_registers_for_AR()); - code_seq_concat(main_cs, - gen_code_stmt(prog.stmt)); - code_seq_concat(main_cs, + code_seq_concat(&main_cs, code_save_registers_for_AR()); + code_seq_concat(&main_cs, + gen_code_seq_stmts(prog.stmts));// Big difference from the Float calculator. Use of gen_code_stmts rather than gen_code_seq_stmt + /*code_seq_concat(&main_cs, code_restore_registers_from_AR()); - code_seq_concat(main_cs, - code_deallocate_stack_space(vars_len_in_bytes)); - code_seq_add_to_end(main_cs, code_exit()); + code_seq_concat(&main_cs, + code_deallocate_stack_space(vars_len_in_bytes));*/ // this section has been muted + code_seq_add_to_end(&main_cs, code_exit(0));// Over here I added a 0 into the code_ exit because of the instruction exit offset should be 0 gen_code_output_program(bf, main_cs); } // Generate code for the var_decls_t vds to out // There are 2 instructions generated for each identifier declared // (one to allocate space and another to initialize that space) -code_seq gen_code_var_decls(var_decls_t vds) +code_seq gen_code_seq_var_decls(var_decls_t vds)// the name was modified { code_seq ret = code_seq_empty(); var_decl_t *vdp = vds.var_decls; while (vdp != NULL) { - // generate these in reverse order, + // generate these in reverse order, // so the addressing offsets work properly - ret = code_seq_concat(gen_code_var_decl(*vdp), ret); + code_seq temp = gen_code_seq_var_decl(*vdp); // Store the result in a variable + code_seq_concat(&temp, ret); // Just call code_seq_concat without assigning to ret vdp = vdp->next; } return ret; @@ -126,24 +127,24 @@ code_seq gen_code_var_decls(var_decls_t vds) // Generate code for a single , vd, // There are 2 instructions generated for each identifier declared // (one to allocate space and another to initialize that space) -code_seq gen_code_var_decl(var_decl_t vd) +code_seq gen_code_seq_var_decl(var_decl_t vd) { - return gen_code_idents(vd.idents, vd.type); + return /*gen_code_idents(vd.idents, vd.type);*/ gen_code_seq_idents(vd.ident_list ); } // Generate code for the identififers in idents with type vt // in reverse order (so the first declared are allocated last). // There are 2 instructions generated for each identifier declared // (one to allocate space and another to initialize that space) -code_seq gen_code_idents(idents_t idents, - type_exp_e vt) +code_seq gen_code_seq_idents(ident_list_t idl) // this was changed+ modified compared to float calculato + { - code_seq ret = code_seq_empty(); - ident_t *idp = idents.idents; + /* code_seq ret = code_seq_empty(); + //ident_t *idp = idents.idents; + ident_t *idp = idl.start; while (idp != NULL) { - code_seq alloc_and_init = code_seq_singleton(code_addi(SP, SP, - -BYTES_PER_WORD)); + code_seq alloc_and_init = code_seq_singleton(code_addi(SP, SP, -BYTES_PER_WORD)); switch (vt) { case float_te: @@ -164,7 +165,27 @@ code_seq gen_code_idents(idents_t idents, ret = code_seq_concat(alloc_and_init, ret); idp = idp->next; } - return ret; + return ret;*/ + code_seq gen_code_seq_idents(ident_list_t idl) + { + code_seq ret = code_seq_empty(); // Start with an empty code sequence + ident_t *idp = idl.start; // Start from the first identifier in the list + + while (idp != NULL) + { + // Generate the code to allocate space for this identifier + // We assume you have a function gen_code_seq_alloc_ident that generates allocation code + code_seq alloc_and_init = gen_code_seq_alloc_ident(idp); + + // Add the allocation and initialization code in reverse order + code_seq_concat(&alloc_and_init, ret); // Concatenate the allocation code with the result + + // Move to the next identifier in the list + idp = idp->next; + } + + return ret; + } } // Generate code for stmt @@ -173,16 +194,22 @@ code_seq gen_code_stmt(stmt_t stmt) switch (stmt.stmt_kind) { case assign_stmt: - return gen_code_assign_stmt(stmt.data.assign_stmt); + return /*gen_code_assign_stmt(stmt.data.assign_stmt);*/ gen_code_seq_assign_stmt(stmt.data.assign_stmt); break; - case begin_stmt: + /*case begin_stmt: return gen_code_begin_stmt(stmt.data.begin_stmt); + break;*/ + case call_stmt: + return gen_code_seq_call_stmt(stmt.data.call_stmt); break; case if_stmt: - return gen_code_if_stmt(stmt.data.if_stmt); + return gen_code_seq_if_stmt(stmt.data.if_stmt); + break; + case while_stmt: + return gen_code_seq_while_stmt(stmt.data.while_stmt); break; case read_stmt: - return gen_code_read_stmt(stmt.data.read_stmt); + return gen_code_seq_read_stmt(stmt.data.read_stmt); break; case write_stmt: return gen_code_write_stmt(stmt.data.write_stmt); @@ -196,7 +223,7 @@ code_seq gen_code_stmt(stmt_t stmt) } // Generate code for stmt -code_seq gen_code_assign_stmt(assign_stmt_t stmt) +code_seq gen_code_seq_assign_stmt(assign_stmt_t stmt) { // can't call gen_code_ident, // since stmt.name is not an ident_t @@ -230,6 +257,15 @@ code_seq gen_code_assign_stmt(assign_stmt_t stmt) } return ret; } +// Generate code for stmt +code_seq gen_code_seq_call_stmt(call_stmt_t stmt) +{ + // can't call gen_code_ident, + // since stmt.name is not an ident_t + code_seq ret; + ret = gen_code_expr(*(stmt.expr)); + return ret; +} // Generate code for stmt code_seq gen_code_begin_stmt(begin_stmt_t stmt) @@ -241,14 +277,14 @@ code_seq gen_code_begin_stmt(begin_stmt_t stmt) // in FLOAT, surrounding scope's base is FP, so that is the static link ret = code_seq_add_to_end(ret, code_add(0, FP, A0)); ret = code_seq_concat(ret, code_save_registers_for_AR()); - ret = code_seq_concat(ret, gen_code_stmts(stmt.stmts)); + ret = code_seq_concat(ret, gen_code_seq_stmts(stmt.stmts)); ret = code_seq_concat(ret, code_restore_registers_from_AR()); ret = code_seq_concat(ret, code_deallocate_stack_space(vars_len_in_bytes)); return ret; } // Generate code for the list of statments given by stmts -code_seq gen_code_stmts(stmts_t stmts) +code_seq gen_code_seq_stmts(stmts_t stmts) { code_seq ret = code_seq_empty(); stmt_t *sp = stmts.stmts; @@ -260,6 +296,16 @@ code_seq gen_code_stmts(stmts_t stmts) return ret; } +// Generate code for stmt +code_seq gen_code_seq_while_stmt(while_stmt_t stmt) +{ + // can't call gen_code_ident, + // since stmt.name is not an ident_t + code_seq ret; + ret = gen_code_expr(*(stmt.expr)); + return ret; +} + // Generate code for the if-statment given by stmt code_seq gen_code_if_stmt(if_stmt_t stmt) { @@ -567,4 +613,22 @@ code_seq gen_code_logical_not_expr(expr_t exp) // push the result on the stack ret = code_seq_concat(ret, code_push_reg_on_stack(AT, bool_te)); return ret; +} +/*Brand new function responsible for generating the code sequence that allocates space for a variable (identifier) on the stack and initializes it with a default value, typically 0 */ +code_seq gen_code_seq_alloc_ident(ident_t *idp) +{ + code_seq ret = code_seq_empty(); // Start with an empty code sequence + + // Assuming that each identifier requires 4 bytes of space + // (adjust this based on your VM's size for each variable) + int size_of_ident = 4; // Adjust the size if necessary + + // 1. Allocate space by subtracting from the stack pointer (SP) + ret = code_seq_add_to_end(ret, code_addi(SP, SP, -size_of_ident)); + + // 2. Initialize the identifier (e.g., set it to 0) + // Assuming that a register 'zero' holds the value 0 + ret = code_seq_add_to_end(ret, code_swr(SP, zero, 0)); // Store 0 into the allocated space + + return ret; // Return the code sequence } \ No newline at end of file diff --git a/gen_code.h b/FromGithub/gen_code.h similarity index 92% rename from gen_code.h rename to FromGithub/gen_code.h index 1ce7c92..04b3301 100644 --- a/gen_code.h +++ b/FromGithub/gen_code.h @@ -36,12 +36,18 @@ extern code_seq gen_code_seq_idents(ident_list_t idents); // Generate code_seq for stmt extern code_seq gen_code_seq_stmt(stmt_t stmt); -// Generate code_seq for stmt +// Generate code_seq for assign stmt extern code_seq gen_code_seq_assign_stmt(assign_stmt_t stmt); +//Generate code_seq for call stmt +extern code_seq gen_code_seq_call_stmt(call_stmt_t stmt); + // Generate code_seq for the list of statements given by stmts to out extern code_seq gen_code_seq_stmts(stmts_t stmts); +//Generate code_seq for while stmt +extern code_seq gen_code_seq_while_stmt(while_stmt_t stmt); + // Generate code_seq for the if-statement given by stmt extern code_seq gen_code_seq_if_stmt(if_stmt_t stmt); @@ -92,4 +98,6 @@ extern code_seq gen_code_seq_number(number_t num); // May also modify SP, HI,LO when executed extern code_seq gen_code_seq_logical_not_expr(expr_t exp); +extern code_seq gen_code_seq_alloc_ident(ident_t *idp); + #endif \ No newline at end of file diff --git a/hw4-gtest0.spl b/FromGithub/hw4-gtest0.spl similarity index 96% rename from hw4-gtest0.spl rename to FromGithub/hw4-gtest0.spl index 9e8844f..6b4ea60 100644 --- a/hw4-gtest0.spl +++ b/FromGithub/hw4-gtest0.spl @@ -1,3 +1,3 @@ -% $Id: hw4-gtest0.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin % no output -end. +% $Id: hw4-gtest0.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin % no output +end. diff --git a/hw4-gtest1.spl b/FromGithub/hw4-gtest1.spl similarity index 96% rename from hw4-gtest1.spl rename to FromGithub/hw4-gtest1.spl index 6bf944c..d3bcf55 100644 --- a/hw4-gtest1.spl +++ b/FromGithub/hw4-gtest1.spl @@ -1,4 +1,4 @@ -% $Id: hw4-gtest1.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - print 8 % prints 8 -end. +% $Id: hw4-gtest1.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + print 8 % prints 8 +end. diff --git a/hw4-gtest2.spl b/FromGithub/hw4-gtest2.spl similarity index 95% rename from hw4-gtest2.spl rename to FromGithub/hw4-gtest2.spl index 79083c9..0983b7c 100644 --- a/hw4-gtest2.spl +++ b/FromGithub/hw4-gtest2.spl @@ -1,7 +1,7 @@ -% $Id: hw4-gtest2.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - if 3 < 4 - then print 10 % prints 10 - else print 11 - end -end. +% $Id: hw4-gtest2.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + if 3 < 4 + then print 10 % prints 10 + else print 11 + end +end. diff --git a/hw4-gtest3.spl b/FromGithub/hw4-gtest3.spl similarity index 96% rename from hw4-gtest3.spl rename to FromGithub/hw4-gtest3.spl index c62a9fe..9286896 100644 --- a/hw4-gtest3.spl +++ b/FromGithub/hw4-gtest3.spl @@ -1,5 +1,5 @@ -% $Id: hw4-gtest3.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - const first = 33; - print first % prints 33 -end. +% $Id: hw4-gtest3.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + const first = 33; + print first % prints 33 +end. diff --git a/hw4-gtest5.spl b/FromGithub/hw4-gtest5.spl similarity index 96% rename from hw4-gtest5.spl rename to FromGithub/hw4-gtest5.spl index e7a8c4b..29d190a 100644 --- a/hw4-gtest5.spl +++ b/FromGithub/hw4-gtest5.spl @@ -1,5 +1,5 @@ -% $Id: hw4-gtest5.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - print 340; % prints 340 - print 2 % prints 2 -end. +% $Id: hw4-gtest5.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + print 340; % prints 340 + print 2 % prints 2 +end. diff --git a/hw4-gtest6.spl b/FromGithub/hw4-gtest6.spl similarity index 95% rename from hw4-gtest6.spl rename to FromGithub/hw4-gtest6.spl index 6a205d4..4ccd48d 100644 --- a/hw4-gtest6.spl +++ b/FromGithub/hw4-gtest6.spl @@ -1,8 +1,8 @@ -% $Id: hw4-gtest6.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - const three = 3; - var four; - four := 4; - print three; % prints 3 - print four % prints 4 -end. +% $Id: hw4-gtest6.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + const three = 3; + var four; + four := 4; + print three; % prints 3 + print four % prints 4 +end. diff --git a/hw4-gtest7.spl b/FromGithub/hw4-gtest7.spl similarity index 94% rename from hw4-gtest7.spl rename to FromGithub/hw4-gtest7.spl index c3cc02f..c146bd8 100644 --- a/hw4-gtest7.spl +++ b/FromGithub/hw4-gtest7.spl @@ -1,10 +1,10 @@ -% $Id: hw4-gtest7.spl,v 1.3 2024/11/11 21:31:41 leavens Exp $ -begin - var x; - var y; - x := -3; - y := 4; - print y; % prints 4 - y := x; - print y % prints -3 -end. +% $Id: hw4-gtest7.spl,v 1.3 2024/11/11 21:31:41 leavens Exp $ +begin + var x; + var y; + x := -3; + y := 4; + print y; % prints 4 + y := x; + print y % prints -3 +end. diff --git a/hw4-gtest8.spl b/FromGithub/hw4-gtest8.spl similarity index 96% rename from hw4-gtest8.spl rename to FromGithub/hw4-gtest8.spl index f85d4be..c859aad 100644 --- a/hw4-gtest8.spl +++ b/FromGithub/hw4-gtest8.spl @@ -1,10 +1,10 @@ -% $Id: hw4-gtest8.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - const aConst = 77; - var aVar, anotherVar; - print aConst; % prints 77 - aVar := aConst; - print aVar; % prints 77 - anotherVar := aConst + 1; - print anotherVar % prints 78 -end. +% $Id: hw4-gtest8.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + const aConst = 77; + var aVar, anotherVar; + print aConst; % prints 77 + aVar := aConst; + print aVar; % prints 77 + anotherVar := aConst + 1; + print anotherVar % prints 78 +end. diff --git a/hw4-gtest9.spl b/FromGithub/hw4-gtest9.spl similarity index 95% rename from hw4-gtest9.spl rename to FromGithub/hw4-gtest9.spl index 067a867..984d6e8 100644 --- a/hw4-gtest9.spl +++ b/FromGithub/hw4-gtest9.spl @@ -1,7 +1,7 @@ -% $Id: hw4-gtest9.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - if 0 == 0 - then print 111 % prints 111 - else print 0 - end -end. +% $Id: hw4-gtest9.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + if 0 == 0 + then print 111 % prints 111 + else print 0 + end +end. diff --git a/hw4-gtestA.spl b/FromGithub/hw4-gtestA.spl similarity index 95% rename from hw4-gtestA.spl rename to FromGithub/hw4-gtestA.spl index 04166fc..d8ef0fe 100644 --- a/hw4-gtestA.spl +++ b/FromGithub/hw4-gtestA.spl @@ -1,8 +1,8 @@ -% $Id: hw4-gtestA.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - const false = 0, true = 1; - if false < true - then print true % prints 1 - else print false - end -end. +% $Id: hw4-gtestA.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + const false = 0, true = 1; + if false < true + then print true % prints 1 + else print false + end +end. diff --git a/hw4-gtestB.spl b/FromGithub/hw4-gtestB.spl similarity index 95% rename from hw4-gtestB.spl rename to FromGithub/hw4-gtestB.spl index 0429323..6d8619e 100644 --- a/hw4-gtestB.spl +++ b/FromGithub/hw4-gtestB.spl @@ -1,16 +1,16 @@ -% $Id: hw4-gtestB.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - const zero = 0, one = 1, two = 2; - const three = 3; - var v1, v2; - var v3, v4; - print zero; % prints 0 - print one; % prints 1 - print two; % prints 2 - v1 := one; - print v1; % prints 1 - v2 := two / one; - print v2; % prints 2 - v3 := (two + 1 + 0) / one; - print v3 % prints 3 -end. +% $Id: hw4-gtestB.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + const zero = 0, one = 1, two = 2; + const three = 3; + var v1, v2; + var v3, v4; + print zero; % prints 0 + print one; % prints 1 + print two; % prints 2 + v1 := one; + print v1; % prints 1 + v2 := two / one; + print v2; % prints 2 + v3 := (two + 1 + 0) / one; + print v3 % prints 3 +end. diff --git a/hw4-gtestC.spl b/FromGithub/hw4-gtestC.spl similarity index 94% rename from hw4-gtestC.spl rename to FromGithub/hw4-gtestC.spl index 9c51507..f3855f4 100644 --- a/hw4-gtestC.spl +++ b/FromGithub/hw4-gtestC.spl @@ -1,12 +1,12 @@ -% $Id: hw4-gtestC.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - const t = 3, f = 4; - const z = 0; - const two = 2; - var a; - var b; - if t <= f - then print t + z % prints 3 - else print two - end -end. +% $Id: hw4-gtestC.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + const t = 3, f = 4; + const z = 0; + const two = 2; + var a; + var b; + if t <= f + then print t + z % prints 3 + else print two + end +end. diff --git a/hw4-gtestD.spl b/FromGithub/hw4-gtestD.spl similarity index 95% rename from hw4-gtestD.spl rename to FromGithub/hw4-gtestD.spl index f7516ca..19ad9c2 100644 --- a/hw4-gtestD.spl +++ b/FromGithub/hw4-gtestD.spl @@ -1,9 +1,9 @@ -% $Id: hw4-gtestD.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ -begin - const t = 3, f = 4; - const z = 0; - const two = 2; - var a; - var b; - if t >= f then print t else print two end % prints 2 -end. +% $Id: hw4-gtestD.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ +begin + const t = 3, f = 4; + const z = 0; + const two = 2; + var a; + var b; + if t >= f then print t else print two end % prints 2 +end. diff --git a/hw4-gtestE.spl b/FromGithub/hw4-gtestE.spl similarity index 95% rename from hw4-gtestE.spl rename to FromGithub/hw4-gtestE.spl index 473cea6..9e6315b 100644 --- a/hw4-gtestE.spl +++ b/FromGithub/hw4-gtestE.spl @@ -1,9 +1,9 @@ -% $Id: hw4-gtestE.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ -begin - const t = 3, f = 4; - const z = 0; - const two = 2; - var a; - var b; - if t > f then print t else print f end % prints 4 -end. +% $Id: hw4-gtestE.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ +begin + const t = 3, f = 4; + const z = 0; + const two = 2; + var a; + var b; + if t > f then print t else print f end % prints 4 +end. diff --git a/hw4-gtestF.spl b/FromGithub/hw4-gtestF.spl similarity index 95% rename from hw4-gtestF.spl rename to FromGithub/hw4-gtestF.spl index 6ec3903..0f5918d 100644 --- a/hw4-gtestF.spl +++ b/FromGithub/hw4-gtestF.spl @@ -1,9 +1,9 @@ -% $Id: hw4-gtestF.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ -begin - const t = 3, f = 4; - const z = 0; - const two = 2; - var a; - var b; - if t < f then print t else print z end % prints 3 -end. +% $Id: hw4-gtestF.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ +begin + const t = 3, f = 4; + const z = 0; + const two = 2; + var a; + var b; + if t < f then print t else print z end % prints 3 +end. diff --git a/hw4-gtestG.spl b/FromGithub/hw4-gtestG.spl similarity index 95% rename from hw4-gtestG.spl rename to FromGithub/hw4-gtestG.spl index 66bca40..7281190 100644 --- a/hw4-gtestG.spl +++ b/FromGithub/hw4-gtestG.spl @@ -1,9 +1,9 @@ -% $Id: hw4-gtestG.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ -begin - const t = 3, f = 4; - const z = 0; - const two = 2; - var a; - var b; - if t != f then print t else print z end % prints 3 -end. +% $Id: hw4-gtestG.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ +begin + const t = 3, f = 4; + const z = 0; + const two = 2; + var a; + var b; + if t != f then print t else print z end % prints 3 +end. diff --git a/hw4-gtestH.spl b/FromGithub/hw4-gtestH.spl similarity index 95% rename from hw4-gtestH.spl rename to FromGithub/hw4-gtestH.spl index 873314b..f934733 100644 --- a/hw4-gtestH.spl +++ b/FromGithub/hw4-gtestH.spl @@ -1,9 +1,9 @@ -% $Id: hw4-gtestH.spl,v 1.3 2024/11/10 12:54:14 leavens Exp $ -begin - const t = 3, f = 4; - const z = 0; - const two = 2; - var a; - var b; - if t == f then print t else print z end % prints 0 -end. +% $Id: hw4-gtestH.spl,v 1.3 2024/11/10 12:54:14 leavens Exp $ +begin + const t = 3, f = 4; + const z = 0; + const two = 2; + var a; + var b; + if t == f then print t else print z end % prints 0 +end. diff --git a/hw4-gtestI.spl b/FromGithub/hw4-gtestI.spl similarity index 96% rename from hw4-gtestI.spl rename to FromGithub/hw4-gtestI.spl index 693b36d..dc9c7e3 100644 --- a/hw4-gtestI.spl +++ b/FromGithub/hw4-gtestI.spl @@ -1,31 +1,31 @@ -% $Id: hw4-gtestI.spl,v 1.4 2024/11/10 12:54:14 leavens Exp $ -begin - const z = 0; - const two = 2; - var t; - var a, b, c; - var d, e, f; - t := 3; f := 4; - print a; % prints 0 - a := t + d; - print a; % prints 3 - print d; % prints 0 - if t == f then print t else print z end; % prints 0 - if t != f then print f else print two end; % prints 4 - if t < f then print two * two * two + 100 % prints 108 - else print t * t end; - if t >= f then print f / f - else print two * t + f end; % prints 10 (i.e., 6+4) - if divisible z by 2 then print f - t else print z end; % prints 1 - if t > f then b := two; c := f * f + b; print c; print b - else print two / two % prints 1 - end; - if t <= f - then - d := t; e := f; - f := d; t := e; - print t; % prints 4 - print f % prints 3 - else print z + (t-t)/t - end -end. +% $Id: hw4-gtestI.spl,v 1.4 2024/11/10 12:54:14 leavens Exp $ +begin + const z = 0; + const two = 2; + var t; + var a, b, c; + var d, e, f; + t := 3; f := 4; + print a; % prints 0 + a := t + d; + print a; % prints 3 + print d; % prints 0 + if t == f then print t else print z end; % prints 0 + if t != f then print f else print two end; % prints 4 + if t < f then print two * two * two + 100 % prints 108 + else print t * t end; + if t >= f then print f / f + else print two * t + f end; % prints 10 (i.e., 6+4) + if divisible z by 2 then print f - t else print z end; % prints 1 + if t > f then b := two; c := f * f + b; print c; print b + else print two / two % prints 1 + end; + if t <= f + then + d := t; e := f; + f := d; t := e; + print t; % prints 4 + print f % prints 3 + else print z + (t-t)/t + end +end. diff --git a/hw4-gtestJ.spl b/FromGithub/hw4-gtestJ.spl similarity index 95% rename from hw4-gtestJ.spl rename to FromGithub/hw4-gtestJ.spl index dcdb9e5..bd34d85 100644 --- a/hw4-gtestJ.spl +++ b/FromGithub/hw4-gtestJ.spl @@ -1,26 +1,26 @@ -% $Id: hw4-gtestJ.spl,v 1.3 2024/11/11 21:36:18 leavens Exp $ -begin - const ten = 10; - const fifty = 50; - var x, y, z, w; - var a, b, c; - print z; % prints 0 - if ten <= fifty - then - x := 10 + 25; - print x; % prints 35 - y := x + 10; - print y; % prints 45 - z := y + (y-x); - print z; % prints 55 - if (z + 0*9999) > fifty % should be true - then - w := ten * x + y + z / 11; - print w % prints 400 - else - print z / 5 + ten - end - else - print a - end -end. +% $Id: hw4-gtestJ.spl,v 1.3 2024/11/11 21:36:18 leavens Exp $ +begin + const ten = 10; + const fifty = 50; + var x, y, z, w; + var a, b, c; + print z; % prints 0 + if ten <= fifty + then + x := 10 + 25; + print x; % prints 35 + y := x + 10; + print y; % prints 45 + z := y + (y-x); + print z; % prints 55 + if (z + 0*9999) > fifty % should be true + then + w := ten * x + y + z / 11; + print w % prints 400 + else + print z / 5 + ten + end + else + print a + end +end. diff --git a/hw4-gtestK.spl b/FromGithub/hw4-gtestK.spl similarity index 94% rename from hw4-gtestK.spl rename to FromGithub/hw4-gtestK.spl index 51db706..fe14aa9 100644 --- a/hw4-gtestK.spl +++ b/FromGithub/hw4-gtestK.spl @@ -1,8 +1,8 @@ -% $Id: hw4-gtestK.spl,v 1.3 2024/11/10 13:11:33 leavens Exp $ -begin - while 0 < 0 - do - print 0 - end; - print 1 % prints 1 -end. +% $Id: hw4-gtestK.spl,v 1.3 2024/11/10 13:11:33 leavens Exp $ +begin + while 0 < 0 + do + print 0 + end; + print 1 % prints 1 +end. diff --git a/hw4-gtestL.spl b/FromGithub/hw4-gtestL.spl similarity index 95% rename from hw4-gtestL.spl rename to FromGithub/hw4-gtestL.spl index 09a6e7f..3acdd06 100644 --- a/hw4-gtestL.spl +++ b/FromGithub/hw4-gtestL.spl @@ -1,22 +1,22 @@ -% $Id: hw4-gtestL.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ -begin - const two = 2; - const three = 3; - var i; - print three; % prints 3 - i := two * three - (two * three - three * two); - while i > (two - two) - do - print i; % prints 6, then 5, 4, 3, 2, 1 - i := i - (three - two + 0 * 5021 * 6414) - end; - if i < 0 - then if i > 0 - then print 0 - else print 0 - end - else if i == 0 - then print (three - two) % prints 1 - end - end -end. +% $Id: hw4-gtestL.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ +begin + const two = 2; + const three = 3; + var i; + print three; % prints 3 + i := two * three - (two * three - three * two); + while i > (two - two) + do + print i; % prints 6, then 5, 4, 3, 2, 1 + i := i - (three - two + 0 * 5021 * 6414) + end; + if i < 0 + then if i > 0 + then print 0 + else print 0 + end + else if i == 0 + then print (three - two) % prints 1 + end + end +end. diff --git a/hw4-gtestM.spl b/FromGithub/hw4-gtestM.spl similarity index 96% rename from hw4-gtestM.spl rename to FromGithub/hw4-gtestM.spl index 6734650..269503f 100644 --- a/hw4-gtestM.spl +++ b/FromGithub/hw4-gtestM.spl @@ -1,18 +1,18 @@ -% $Id: hw4-gtestM.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ -begin - const seven = 7; - var x; - begin - print seven; % prints 7 - x := seven / ((100 * 100) / (100 * 100)); - while x > 1 - do - print x; % prints 7, 11, 17, 26, 13, 20, 10, 5, 8, 4, 2 - if divisible x by 2 - then x := x / 2 - else x := (3 * x + 1) / 2 - end - end; - print x + (seven - seven + (6 - (5+1)) * 3402) % prints 1 - end -end. +% $Id: hw4-gtestM.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ +begin + const seven = 7; + var x; + begin + print seven; % prints 7 + x := seven / ((100 * 100) / (100 * 100)); + while x > 1 + do + print x; % prints 7, 11, 17, 26, 13, 20, 10, 5, 8, 4, 2 + if divisible x by 2 + then x := x / 2 + else x := (3 * x + 1) / 2 + end + end; + print x + (seven - seven + (6 - (5+1)) * 3402) % prints 1 + end +end. diff --git a/hw4-gtestN.spl b/FromGithub/hw4-gtestN.spl similarity index 94% rename from hw4-gtestN.spl rename to FromGithub/hw4-gtestN.spl index 4caf4c5..f2eb3e2 100644 --- a/hw4-gtestN.spl +++ b/FromGithub/hw4-gtestN.spl @@ -1,25 +1,25 @@ -% $Id: hw4-gtestN.spl,v 1.4 2024/11/11 18:56:53 leavens Exp $ -% various statments -begin - const pi = 31, e = 3; - var x, y, z; - begin - x := 3*4-2/5; % x is 12 = 12-0 - if x > 0 - then x := y+1 % x is 1 - else - x := 1; - y := z - end; - while x <= 10 - do - x := x+1 - end; - print x; % prints 11 - print y+2; % prints 2 - if divisible y by 2 - then y := y / 2 + 3 % y is 3 - end; - print y % prints 3 - end -end. +% $Id: hw4-gtestN.spl,v 1.4 2024/11/11 18:56:53 leavens Exp $ +% various statments +begin + const pi = 31, e = 3; + var x, y, z; + begin + x := 3*4-2/5; % x is 12 = 12-0 + if x > 0 + then x := y+1 % x is 1 + else + x := 1; + y := z + end; + while x <= 10 + do + x := x+1 + end; + print x; % prints 11 + print y+2; % prints 2 + if divisible y by 2 + then y := y / 2 + 3 % y is 3 + end; + print y % prints 3 + end +end. diff --git a/hw4-gtestO.spl b/FromGithub/hw4-gtestO.spl similarity index 94% rename from hw4-gtestO.spl rename to FromGithub/hw4-gtestO.spl index bdaa427..89de84c 100644 --- a/hw4-gtestO.spl +++ b/FromGithub/hw4-gtestO.spl @@ -1,15 +1,15 @@ -% $Id: hw4-gtestO.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ -begin -var x; - begin - x := 2-1; - if x >= 1 - then print x % prints 1 - end; - while x <= 10 - do - x := x+1 - end; - print x % prints 11 - end -end. +% $Id: hw4-gtestO.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ +begin +var x; + begin + x := 2-1; + if x >= 1 + then print x % prints 1 + end; + while x <= 10 + do + x := x+1 + end; + print x % prints 11 + end +end. diff --git a/hw4-gtestP.spl b/FromGithub/hw4-gtestP.spl similarity index 95% rename from hw4-gtestP.spl rename to FromGithub/hw4-gtestP.spl index 7b0e307..0551727 100644 --- a/hw4-gtestP.spl +++ b/FromGithub/hw4-gtestP.spl @@ -1,29 +1,29 @@ -% $Id: hw4-gtestP.spl,v 1.4 2024/11/10 12:54:14 leavens Exp $ -begin - const a = 1, b = 3; - const c = 4, d = 6; - var aVar, anotherVar; - var x; - begin - aVar := -1; - anotherVar := aVar - 2 - 3/1 - 6*aVar; - if anotherVar >= aVar - then - print 32; % prints 32 - print 10; % prints 10 - anotherVar := anotherVar / 12 + 2; - while (anotherVar*2) < 3 - do - begin end; - anotherVar := 0 - end - else - if 3 < 2 - then - if 7 > 5 then x := 3 end - else x := 2 * 3 - 5/4; - print x - end - end - end -end. +% $Id: hw4-gtestP.spl,v 1.4 2024/11/10 12:54:14 leavens Exp $ +begin + const a = 1, b = 3; + const c = 4, d = 6; + var aVar, anotherVar; + var x; + begin + aVar := -1; + anotherVar := aVar - 2 - 3/1 - 6*aVar; + if anotherVar >= aVar + then + print 32; % prints 32 + print 10; % prints 10 + anotherVar := anotherVar / 12 + 2; + while (anotherVar*2) < 3 + do + begin end; + anotherVar := 0 + end + else + if 3 < 2 + then + if 7 > 5 then x := 3 end + else x := 2 * 3 - 5/4; + print x + end + end + end +end. diff --git a/hw4-gtestQ.spl b/FromGithub/hw4-gtestQ.spl similarity index 94% rename from hw4-gtestQ.spl rename to FromGithub/hw4-gtestQ.spl index 6a62aae..0c0d1ba 100644 --- a/hw4-gtestQ.spl +++ b/FromGithub/hw4-gtestQ.spl @@ -1,9 +1,9 @@ -% $Id: hw4-gtestQ.spl,v 1.1 2024/11/12 02:04:20 leavens Exp $ -begin - if divisible 33 by 3 - then - print 86 % prints 86 - else - print 55 - end -end. +% $Id: hw4-gtestQ.spl,v 1.1 2024/11/12 02:04:20 leavens Exp $ +begin + if divisible 33 by 3 + then + print 86 % prints 86 + else + print 55 + end +end. diff --git a/hw4-gtestR.spl b/FromGithub/hw4-gtestR.spl similarity index 94% rename from hw4-gtestR.spl rename to FromGithub/hw4-gtestR.spl index f76436c..509dbd3 100644 --- a/hw4-gtestR.spl +++ b/FromGithub/hw4-gtestR.spl @@ -1,9 +1,9 @@ -% $Id: hw4-gtestR.spl,v 1.1 2024/11/12 02:04:20 leavens Exp $ -begin - if divisible 8 by 3 - then - print 1 - else - print 99 % prints 99 - end -end. +% $Id: hw4-gtestR.spl,v 1.1 2024/11/12 02:04:20 leavens Exp $ +begin + if divisible 8 by 3 + then + print 1 + else + print 99 % prints 99 + end +end. diff --git a/hw4-gtestS.spl b/FromGithub/hw4-gtestS.spl similarity index 94% rename from hw4-gtestS.spl rename to FromGithub/hw4-gtestS.spl index b0a92af..0c92456 100644 --- a/hw4-gtestS.spl +++ b/FromGithub/hw4-gtestS.spl @@ -1,11 +1,11 @@ -% $Id: hw4-gtestS.spl,v 1.1 2024/11/12 02:04:20 leavens Exp $ -begin - var ff; - ff := 44; - if divisible ff by 11 - then - print 23 % prints 23 - else - print 97 - end -end. +% $Id: hw4-gtestS.spl,v 1.1 2024/11/12 02:04:20 leavens Exp $ +begin + var ff; + ff := 44; + if divisible ff by 11 + then + print 23 % prints 23 + else + print 97 + end +end. diff --git a/hw4-gtestT.spl b/FromGithub/hw4-gtestT.spl similarity index 94% rename from hw4-gtestT.spl rename to FromGithub/hw4-gtestT.spl index a54ef2f..3d44f3b 100644 --- a/hw4-gtestT.spl +++ b/FromGithub/hw4-gtestT.spl @@ -1,16 +1,16 @@ -% $Id: hw4-gtestT.spl,v 1.1 2024/11/12 02:04:20 leavens Exp $ -begin - const seventeen = 17; - begin - var seventeen2; - begin - seventeen2 := seventeen * seventeen; - if divisible seventeen2 by 11 - then - print 86 - else - print 42 % prints 42 - end - end - end -end. +% $Id: hw4-gtestT.spl,v 1.1 2024/11/12 02:04:20 leavens Exp $ +begin + const seventeen = 17; + begin + var seventeen2; + begin + seventeen2 := seventeen * seventeen; + if divisible seventeen2 by 11 + then + print 86 + else + print 42 % prints 42 + end + end + end +end. diff --git a/hw4-read-test0.spl b/FromGithub/hw4-read-test0.spl similarity index 93% rename from hw4-read-test0.spl rename to FromGithub/hw4-read-test0.spl index 945b59a..65fc010 100644 --- a/hw4-read-test0.spl +++ b/FromGithub/hw4-read-test0.spl @@ -1,8 +1,8 @@ -% $Id: hw4-read-test0.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ -begin - var c; - begin - read c; - print c - end -end. +% $Id: hw4-read-test0.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ +begin + var c; + begin + read c; + print c + end +end. diff --git a/hw4-read-test1.spl b/FromGithub/hw4-read-test1.spl similarity index 93% rename from hw4-read-test1.spl rename to FromGithub/hw4-read-test1.spl index 57fe061..6f5c77c 100644 --- a/hw4-read-test1.spl +++ b/FromGithub/hw4-read-test1.spl @@ -1,12 +1,12 @@ -% $Id: hw4-read-test1.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ -begin - var rd; - begin - read rd; - while rd > 0 - do - print rd; - read rd - end - end -end. +% $Id: hw4-read-test1.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ +begin + var rd; + begin + read rd; + while rd > 0 + do + print rd; + read rd + end + end +end. diff --git a/hw4-vmtest0.spl b/FromGithub/hw4-vmtest0.spl similarity index 96% rename from hw4-vmtest0.spl rename to FromGithub/hw4-vmtest0.spl index 2c7e635..593a2fe 100644 --- a/hw4-vmtest0.spl +++ b/FromGithub/hw4-vmtest0.spl @@ -1,3 +1,3 @@ -% $Id: hw4-vmtest0.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin -end. +% $Id: hw4-vmtest0.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin +end. diff --git a/hw4-vmtest1.spl b/FromGithub/hw4-vmtest1.spl similarity index 96% rename from hw4-vmtest1.spl rename to FromGithub/hw4-vmtest1.spl index f7f3524..441be3d 100644 --- a/hw4-vmtest1.spl +++ b/FromGithub/hw4-vmtest1.spl @@ -1,4 +1,4 @@ -% $Id: hw4-vmtest1.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - print 10 % prints 10 -end. +% $Id: hw4-vmtest1.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + print 10 % prints 10 +end. diff --git a/hw4-vmtest2.spl b/FromGithub/hw4-vmtest2.spl similarity index 94% rename from hw4-vmtest2.spl rename to FromGithub/hw4-vmtest2.spl index 111f9da..c565076 100644 --- a/hw4-vmtest2.spl +++ b/FromGithub/hw4-vmtest2.spl @@ -1,8 +1,8 @@ -% $Id: hw4-vmtest2.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - var x; - begin - x := 5; - print x % prints 5 - end -end. +% $Id: hw4-vmtest2.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + var x; + begin + x := 5; + print x % prints 5 + end +end. diff --git a/hw4-vmtest3.spl b/FromGithub/hw4-vmtest3.spl similarity index 94% rename from hw4-vmtest3.spl rename to FromGithub/hw4-vmtest3.spl index 4deb444..e4d53e4 100644 --- a/hw4-vmtest3.spl +++ b/FromGithub/hw4-vmtest3.spl @@ -1,9 +1,9 @@ -% $Id: hw4-vmtest3.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - const five = 5; - var x; - begin - x := five; - print x % prints 5 - end -end. +% $Id: hw4-vmtest3.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + const five = 5; + var x; + begin + x := five; + print x % prints 5 + end +end. diff --git a/hw4-vmtest4.spl b/FromGithub/hw4-vmtest4.spl similarity index 95% rename from hw4-vmtest4.spl rename to FromGithub/hw4-vmtest4.spl index 98a82dc..ba0010c 100644 --- a/hw4-vmtest4.spl +++ b/FromGithub/hw4-vmtest4.spl @@ -1,5 +1,5 @@ -% $Id: hw4-vmtest4.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - begin end; - begin end -end. +% $Id: hw4-vmtest4.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + begin end; + begin end +end. diff --git a/hw4-vmtest5.spl b/FromGithub/hw4-vmtest5.spl similarity index 94% rename from hw4-vmtest5.spl rename to FromGithub/hw4-vmtest5.spl index 38b0005..e1b38a8 100644 --- a/hw4-vmtest5.spl +++ b/FromGithub/hw4-vmtest5.spl @@ -1,10 +1,10 @@ -% $Id: hw4-vmtest5.spl,v 1.6 2024/09/17 21:48:53 leavens Exp $ -begin - var x, y; - begin - y := 33; - print y; % prints 33 - x := y + 22; - print x % prints 55 - end -end. +% $Id: hw4-vmtest5.spl,v 1.6 2024/09/17 21:48:53 leavens Exp $ +begin + var x, y; + begin + y := 33; + print y; % prints 33 + x := y + 22; + print x % prints 55 + end +end. diff --git a/hw4-vmtest6.spl b/FromGithub/hw4-vmtest6.spl similarity index 96% rename from hw4-vmtest6.spl rename to FromGithub/hw4-vmtest6.spl index 7f06f1f..e301d66 100644 --- a/hw4-vmtest6.spl +++ b/FromGithub/hw4-vmtest6.spl @@ -1,13 +1,13 @@ -% $Id: hw4-vmtest6.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - const nl = 10, y = 121; - var x, z, q; - begin - x := nl+1+0-0*10/10; - print x; % prints 11 - z := x - x + y - (1 - 2 + 1); - print z + q; % prints 121 - q := x / z; - print q-0-0 % prints 0 - end -end. +% $Id: hw4-vmtest6.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + const nl = 10, y = 121; + var x, z, q; + begin + x := nl+1+0-0*10/10; + print x; % prints 11 + z := x - x + y - (1 - 2 + 1); + print z + q; % prints 121 + q := x / z; + print q-0-0 % prints 0 + end +end. diff --git a/hw4-vmtest7.spl b/FromGithub/hw4-vmtest7.spl similarity index 94% rename from hw4-vmtest7.spl rename to FromGithub/hw4-vmtest7.spl index dee869e..70ef3b2 100644 --- a/hw4-vmtest7.spl +++ b/FromGithub/hw4-vmtest7.spl @@ -1,13 +1,13 @@ -% $Id: hw4-vmtest7.spl,v 1.4 2024/09/17 21:48:53 leavens Exp $ -begin - const Y = 89, N = 78, nl =10; - begin - if 99 > 86 - then - print Y % prints 89 - else - print N - end; - print nl % prints 10 - end -end. +% $Id: hw4-vmtest7.spl,v 1.4 2024/09/17 21:48:53 leavens Exp $ +begin + const Y = 89, N = 78, nl =10; + begin + if 99 > 86 + then + print Y % prints 89 + else + print N + end; + print nl % prints 10 + end +end. diff --git a/hw4-vmtest8.spl b/FromGithub/hw4-vmtest8.spl similarity index 94% rename from hw4-vmtest8.spl rename to FromGithub/hw4-vmtest8.spl index eee2d9c..cb29722 100644 --- a/hw4-vmtest8.spl +++ b/FromGithub/hw4-vmtest8.spl @@ -1,14 +1,14 @@ -% $Id: hw4-vmtest8.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - var x, y; - begin - if 99 < 86 - then - x := +72 - else - y := 1 - end; - print x; % prints 0 - print y % prints 1 - end -end. +% $Id: hw4-vmtest8.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + var x, y; + begin + if 99 < 86 + then + x := +72 + else + y := 1 + end; + print x; % prints 0 + print y % prints 1 + end +end. diff --git a/hw4-vmtest9.spl b/FromGithub/hw4-vmtest9.spl similarity index 94% rename from hw4-vmtest9.spl rename to FromGithub/hw4-vmtest9.spl index dafb28d..4a2bda4 100644 --- a/hw4-vmtest9.spl +++ b/FromGithub/hw4-vmtest9.spl @@ -1,22 +1,22 @@ -% $Id: hw4-vmtest9.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - const q = 7; - var x, y, z; - begin - x := 86; - print x; % prints 86 - y := 99; - print y; % prints 99 - z := 1001; - print z; % prints 1001 - print (x-y); % prints -13 - if divisible (x-y) by 2 - then - y := y-1*z; - print y - else - x := z+1+q; - print x % prints 1009 - end - end -end. +% $Id: hw4-vmtest9.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + const q = 7; + var x, y, z; + begin + x := 86; + print x; % prints 86 + y := 99; + print y; % prints 99 + z := 1001; + print z; % prints 1001 + print (x-y); % prints -13 + if divisible (x-y) by 2 + then + y := y-1*z; + print y + else + x := z+1+q; + print x % prints 1009 + end + end +end. diff --git a/hw4-vmtestA.spl b/FromGithub/hw4-vmtestA.spl similarity index 94% rename from hw4-vmtestA.spl rename to FromGithub/hw4-vmtestA.spl index 31ec85f..951a479 100644 --- a/hw4-vmtestA.spl +++ b/FromGithub/hw4-vmtestA.spl @@ -1,16 +1,16 @@ -% $Id: hw4-vmtestA.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - const achar = 97; - var c; - var i; - begin - i := 0; - while i < 10 - do - c := achar + i; - % prints 98, 99, 100, 101, 102, 103, 104, 105, 106, 107 - print c+1; - i := i+1 - end - end -end. +% $Id: hw4-vmtestA.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + const achar = 97; + var c; + var i; + begin + i := 0; + while i < 10 + do + c := achar + i; + % prints 98, 99, 100, 101, 102, 103, 104, 105, 106, 107 + print c+1; + i := i+1 + end + end +end. diff --git a/hw4-vmtestB.spl b/FromGithub/hw4-vmtestB.spl similarity index 95% rename from hw4-vmtestB.spl rename to FromGithub/hw4-vmtestB.spl index 863152e..aa1930b 100644 --- a/hw4-vmtestB.spl +++ b/FromGithub/hw4-vmtestB.spl @@ -1,7 +1,7 @@ -% $Id: hw4-vmtestB.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ -begin - const c = 32; - const five = 5, three = 3; - var x, y, z; - var i, j, k; -end. +% $Id: hw4-vmtestB.spl,v 1.2 2024/09/17 21:48:53 leavens Exp $ +begin + const c = 32; + const five = 5, three = 3; + var x, y, z; + var i, j, k; +end. diff --git a/hw4-vmtestC.spl b/FromGithub/hw4-vmtestC.spl similarity index 94% rename from hw4-vmtestC.spl rename to FromGithub/hw4-vmtestC.spl index df68d49..cb97c57 100644 --- a/hw4-vmtestC.spl +++ b/FromGithub/hw4-vmtestC.spl @@ -1,22 +1,22 @@ -% $Id: hw4-vmtestC.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ -begin - const c = 48; - var i, j; - begin - i := 0; - print i; % prints 0 - j := c; - print j; % prints 48 - while i <= 1 - do - print c+i+4; % prints 52, 53 - while j < c+i+4 - do - print j; % prints 48, 49, 50, 51, 52 - j := j+1 - end; - i := i+1 - end; - print i % prints 2 - end -end. +% $Id: hw4-vmtestC.spl,v 1.3 2024/09/17 21:48:53 leavens Exp $ +begin + const c = 48; + var i, j; + begin + i := 0; + print i; % prints 0 + j := c; + print j; % prints 48 + while i <= 1 + do + print c+i+4; % prints 52, 53 + while j < c+i+4 + do + print j; % prints 48, 49, 50, 51, 52 + j := j+1 + end; + i := i+1 + end; + print i % prints 2 + end +end. diff --git a/id_attrs.c b/FromGithub/id_attrs.c old mode 100755 new mode 100644 similarity index 96% rename from id_attrs.c rename to FromGithub/id_attrs.c index cd4eca6..3224a36 --- a/id_attrs.c +++ b/FromGithub/id_attrs.c @@ -1,50 +1,50 @@ -/* $Id: id_attrs.c,v 1.10 2023/11/17 21:56:45 leavens Exp $ */ -// Attributes of identifiers in the symbol table -#include -#include -#include "utilities.h" -#include "id_attrs.h" - -// Return a freshly allocated id_attrs struct -// with its field file_loc set to floc, kind set to k, -// and its offset_count set to ofst_cnt. -// If there is no space, bail with an error message, -// so this should never return NULL. -id_attrs *id_attrs_create(file_location floc, id_kind k, - unsigned int ofst_cnt) -{ - id_attrs *ret = (id_attrs *)malloc(sizeof(id_attrs)); - if (ret == NULL) { - bail_with_error("No space to allocate id_attrs!"); - } - ret->file_loc = floc; - ret->kind = k; - ret->offset_count = ofst_cnt; - return ret; -} - -// Return a freshly allocated id_attrs struct for a procedure -// declared at floc. -// If there is no space, bail with an error message, -// so this should never return NULL. -extern id_attrs *id_attrs_proc_create(file_location floc) -{ - id_attrs *ret = (id_attrs *)malloc(sizeof(id_attrs)); - if (ret == NULL) { - bail_with_error("No space to allocate id_attrs!"); - } - ret->file_loc = floc; - ret->kind = procedure_idk; - return ret; -} - - -// Return a lowercase version of the kind's name as a string -// (i.e. if k == variable_idk, return "variable" -// else if k == constant_idk, return "constant", -// else if k == procedure_idk, return "procedure") -const char *id_attrs_id_kind_string(id_kind k) -{ - static const char *kind_names[3] = {"constant", "variable", "procedure"}; - return kind_names[k]; -} +/* $Id: id_attrs.c,v 1.10 2023/11/17 21:56:45 leavens Exp $ */ +// Attributes of identifiers in the symbol table +#include +#include +#include "utilities.h" +#include "id_attrs.h" + +// Return a freshly allocated id_attrs struct +// with its field file_loc set to floc, kind set to k, +// and its offset_count set to ofst_cnt. +// If there is no space, bail with an error message, +// so this should never return NULL. +id_attrs *id_attrs_create(file_location floc, id_kind k, + unsigned int ofst_cnt) +{ + id_attrs *ret = (id_attrs *)malloc(sizeof(id_attrs)); + if (ret == NULL) { + bail_with_error("No space to allocate id_attrs!"); + } + ret->file_loc = floc; + ret->kind = k; + ret->offset_count = ofst_cnt; + return ret; +} + +// Return a freshly allocated id_attrs struct for a procedure +// declared at floc. +// If there is no space, bail with an error message, +// so this should never return NULL. +extern id_attrs *id_attrs_proc_create(file_location floc) +{ + id_attrs *ret = (id_attrs *)malloc(sizeof(id_attrs)); + if (ret == NULL) { + bail_with_error("No space to allocate id_attrs!"); + } + ret->file_loc = floc; + ret->kind = procedure_idk; + return ret; +} + + +// Return a lowercase version of the kind's name as a string +// (i.e. if k == variable_idk, return "variable" +// else if k == constant_idk, return "constant", +// else if k == procedure_idk, return "procedure") +const char *id_attrs_id_kind_string(id_kind k) +{ + static const char *kind_names[3] = {"constant", "variable", "procedure"}; + return kind_names[k]; +} diff --git a/id_attrs.h b/FromGithub/id_attrs.h old mode 100755 new mode 100644 similarity index 97% rename from id_attrs.h rename to FromGithub/id_attrs.h index 73070c1..74779aa --- a/id_attrs.h +++ b/FromGithub/id_attrs.h @@ -1,39 +1,39 @@ -/* $Id: id_attrs.h,v 1.11 2024/10/23 13:06:37 leavens Exp $ */ -#ifndef _ID_ATTRS_H -#define _ID_ATTRS_H -#include "file_location.h" - -// kinds of entries in the symbol table -typedef enum {constant_idk, variable_idk, procedure_idk} id_kind; - -// attributes of identifiers in the symbol table -typedef struct { - // file_loc is the source file location of the identifier's declaration - file_location file_loc; - id_kind kind; // kind of identifier - // offset_count is the number of constant or variable decls before this one - // in this scope - unsigned int offset_count; -} id_attrs; - -// Return a freshly allocated id_attrs struct -// with its field file_loc set to floc, kind set to k, -// and its offset_count set to ofst_cnt. -// If there is no space, bail with an error message, -// so this should never return NULL. -extern id_attrs *id_attrs_create(file_location floc, id_kind k, - unsigned int ofst_cnt); - -// Return a freshly allocated id_attrs struct for a procedure -// declared at floc. -// If there is no space, bail with an error message, -// so this should never return NULL. -extern id_attrs *id_attrs_proc_create(file_location floc); - -// Return a lowercase version of the kind's name as a string -// (i.e. if k == variable_idk, return "variable" -// else if k == constant_idk, return "constant", -// else if k == procedure_idk, return "procedure") -extern const char *id_attrs_id_kind_string(id_kind k); - -#endif +/* $Id: id_attrs.h,v 1.11 2024/10/23 13:06:37 leavens Exp $ */ +#ifndef _ID_ATTRS_H +#define _ID_ATTRS_H +#include "file_location.h" + +// kinds of entries in the symbol table +typedef enum {constant_idk, variable_idk, procedure_idk} id_kind; + +// attributes of identifiers in the symbol table +typedef struct { + // file_loc is the source file location of the identifier's declaration + file_location file_loc; + id_kind kind; // kind of identifier + // offset_count is the number of constant or variable decls before this one + // in this scope + unsigned int offset_count; +} id_attrs; + +// Return a freshly allocated id_attrs struct +// with its field file_loc set to floc, kind set to k, +// and its offset_count set to ofst_cnt. +// If there is no space, bail with an error message, +// so this should never return NULL. +extern id_attrs *id_attrs_create(file_location floc, id_kind k, + unsigned int ofst_cnt); + +// Return a freshly allocated id_attrs struct for a procedure +// declared at floc. +// If there is no space, bail with an error message, +// so this should never return NULL. +extern id_attrs *id_attrs_proc_create(file_location floc); + +// Return a lowercase version of the kind's name as a string +// (i.e. if k == variable_idk, return "variable" +// else if k == constant_idk, return "constant", +// else if k == procedure_idk, return "procedure") +extern const char *id_attrs_id_kind_string(id_kind k); + +#endif diff --git a/FromGithub/id_attrs.o b/FromGithub/id_attrs.o new file mode 100644 index 0000000..b064c73 Binary files /dev/null and b/FromGithub/id_attrs.o differ diff --git a/id_use.c b/FromGithub/id_use.c old mode 100755 new mode 100644 similarity index 96% rename from id_use.c rename to FromGithub/id_use.c index b4fc528..b322bee --- a/id_use.c +++ b/FromGithub/id_use.c @@ -1,47 +1,47 @@ -/* $Id: id_use.c,v 1.10 2024/10/23 13:13:07 leavens Exp $ */ -#include -#include "machine_types.h" -#include "id_use.h" -#include "utilities.h" - -// Requires: attrs != NULL -// Return a (pointer to a fresh) id_use struct containing the attributes -// given by attrs and the information about the number of lexical levels -// outward from the current scope where the declaration was found. -// If there is no space, bail with an error message, -// so this should never return NULL. -extern id_use *id_use_create(id_attrs *attrs, unsigned int levelsOut) -{ - id_use *ret = (id_use *)malloc(sizeof(id_use)); - if (ret == NULL) { - bail_with_error("No space to allocate id_use!"); - } - ret->attrs = attrs; - ret->levelsOutward = levelsOut; - // Shouldn't create a label for procedures here! - // A label should only be created when creating the proc_decl's AST! - return ret; -} - -// Requires: idu != NULL -// Return a pointer to the attributes of this id_use -// and the result will never be NULL -id_attrs *id_use_get_attrs(id_use *idu) -{ - assert(idu != NULL); - return idu->attrs; -} - - -// Requires: idu != NULL -// Return (a pointer to) the lexical address for idu. -lexical_address *id_use_2_lexical_address(id_use *idu) -{ - lexical_address *ret = (lexical_address *)malloc(sizeof(lexical_address)); - if (ret == NULL) { - bail_with_error("No space to allocate lexical_address!"); - } - ret->levelsOutward = idu->levelsOutward; - ret->offsetInAR = idu->attrs->offset_count; - return ret; -} +/* $Id: id_use.c,v 1.10 2024/10/23 13:13:07 leavens Exp $ */ +#include +#include "machine_types.h" +#include "id_use.h" +#include "utilities.h" + +// Requires: attrs != NULL +// Return a (pointer to a fresh) id_use struct containing the attributes +// given by attrs and the information about the number of lexical levels +// outward from the current scope where the declaration was found. +// If there is no space, bail with an error message, +// so this should never return NULL. +extern id_use *id_use_create(id_attrs *attrs, unsigned int levelsOut) +{ + id_use *ret = (id_use *)malloc(sizeof(id_use)); + if (ret == NULL) { + bail_with_error("No space to allocate id_use!"); + } + ret->attrs = attrs; + ret->levelsOutward = levelsOut; + // Shouldn't create a label for procedures here! + // A label should only be created when creating the proc_decl's AST! + return ret; +} + +// Requires: idu != NULL +// Return a pointer to the attributes of this id_use +// and the result will never be NULL +id_attrs *id_use_get_attrs(id_use *idu) +{ + assert(idu != NULL); + return idu->attrs; +} + + +// Requires: idu != NULL +// Return (a pointer to) the lexical address for idu. +lexical_address *id_use_2_lexical_address(id_use *idu) +{ + lexical_address *ret = (lexical_address *)malloc(sizeof(lexical_address)); + if (ret == NULL) { + bail_with_error("No space to allocate lexical_address!"); + } + ret->levelsOutward = idu->levelsOutward; + ret->offsetInAR = idu->attrs->offset_count; + return ret; +} diff --git a/id_use.h b/FromGithub/id_use.h old mode 100755 new mode 100644 similarity index 97% rename from id_use.h rename to FromGithub/id_use.h index 9f00847..03d570e --- a/id_use.h +++ b/FromGithub/id_use.h @@ -1,32 +1,32 @@ -/* $Id: id_use.h,v 1.7 2024/10/23 13:13:07 leavens Exp $ */ -#ifndef _ID_USE_H -#define _ID_USE_H -#include "id_attrs.h" -// we'll use lexical_address in HW4 -#include "lexical_address.h" - -// An id_use struct gives all the information from -// a lookup in the symbol table for a name: -// the (pointer to the) id_attrs (attributes) -// and the number of lexical levels out -// from the current scope where the name was declared. -typedef struct { - id_attrs *attrs; - unsigned int levelsOutward; -} id_use; - -// Requires: attrs != NULL -// Return a (pointer to a fresh) id_use struct containing the attributes -// given by attrs and the information about the number of lexical levels -// outward from the current scope where the declaration was found. -extern id_use *id_use_create(id_attrs *attrs, unsigned int levelsOut); - -// Requires: idu != NULL -// Return a pointer to the attributes of this id_use -// and the result will never be NULL -extern id_attrs *id_use_get_attrs(id_use *idu); - -// Requires: idu != NULL -// Return (a pointer to) the lexical address for idu. -extern lexical_address *id_use_2_lexical_address(id_use *idu); -#endif +/* $Id: id_use.h,v 1.7 2024/10/23 13:13:07 leavens Exp $ */ +#ifndef _ID_USE_H +#define _ID_USE_H +#include "id_attrs.h" +// we'll use lexical_address in HW4 +#include "lexical_address.h" + +// An id_use struct gives all the information from +// a lookup in the symbol table for a name: +// the (pointer to the) id_attrs (attributes) +// and the number of lexical levels out +// from the current scope where the name was declared. +typedef struct { + id_attrs *attrs; + unsigned int levelsOutward; +} id_use; + +// Requires: attrs != NULL +// Return a (pointer to a fresh) id_use struct containing the attributes +// given by attrs and the information about the number of lexical levels +// outward from the current scope where the declaration was found. +extern id_use *id_use_create(id_attrs *attrs, unsigned int levelsOut); + +// Requires: idu != NULL +// Return a pointer to the attributes of this id_use +// and the result will never be NULL +extern id_attrs *id_use_get_attrs(id_use *idu); + +// Requires: idu != NULL +// Return (a pointer to) the lexical address for idu. +extern lexical_address *id_use_2_lexical_address(id_use *idu); +#endif diff --git a/FromGithub/id_use.o b/FromGithub/id_use.o new file mode 100644 index 0000000..25c3320 Binary files /dev/null and b/FromGithub/id_use.o differ diff --git a/instruction.c b/FromGithub/instruction.c old mode 100755 new mode 100644 similarity index 96% rename from instruction.c rename to FromGithub/instruction.c index ef37eeb..73c9f02 --- a/instruction.c +++ b/FromGithub/instruction.c @@ -1,575 +1,575 @@ -// $Id: instruction.c,v 1.7 2024/11/10 21:09:43 leavens Exp $ -#include -#include -#include "bof.h" -#include "instruction.h" -#include "regname.h" -#include "utilities.h" -#include "machine_types.h" - -#define INSTR_BUF_SIZE 512 - -// the following declaration isn't in everywhere ... -extern char *strdup(const char *s); - -// space to hold one instruction's assembly language form -static char instr_buf[INSTR_BUF_SIZE]; - -// Return the instruction type of the given opcode -instr_type instruction_type(bin_instr_t i) { - switch (i.comp.op) { // need to pretend a type to read the op field - case COMP_O: - return comp_instr_type; - break; - case OTHC_O: - if (i.othc.func == SYS_F) { - return syscall_instr_type; - } else { - assert(i.othc.op != COMP_O); - assert(i.othc.func != NOP_F); - return other_comp_instr_type; - } - break; - case ADDI_O: case ANDI_O: case BORI_O: case NORI_O: case XORI_O: - case BEQ_O: case BGEZ_O: case BGTZ_O: case BLEZ_O: case BLTZ_O: - case BNE_O: - return immed_instr_type; - break; - case JMPA_O: case CALL_O: case RTN_O: - return jump_instr_type; - break; - default: - return error_instr_type; - break; - } -} - -// Requires: bof is open for reading in binary -// Read a single instruction (in binary) from bf and return it, -// but exit with an error if there is a problem. -bin_instr_t instruction_read(BOFFILE bf) -{ - bin_instr_t bi; - size_t rd = fread(&bi, sizeof(bi), 1, bf.fileptr); - if (rd != 1) { - bail_with_error("Cannot read instruction from %s (read %d instrs)", - bf.filename, rd); - } - return bi; -} - -// Requires: bf is open for writing in binary -// Write the given binary instruction to bf, -// but exit with an error if there is a problem. -static void write_bin_instr(BOFFILE bf, bin_instr_t i) -{ - size_t wr = fwrite(&i, sizeof(i), 1, bf.fileptr); - if (wr != 1) { - bail_with_error("Cannot write binary instr to %s", bf.filename); - } -} - -// Requires: bof is open for writing in binary -// Write the binary instruction bi to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_bin_instr(BOFFILE bf, bin_instr_t bi) -{ - switch (instruction_type(bi)) { - case comp_instr_type: - instruction_write_compInstr(bf, bi.comp); - break; - case other_comp_instr_type: - instruction_write_otherCompInstr(bf, bi.othc); - break; - case immed_instr_type: - instruction_write_immedInstr(bf, bi.immed); - break; - case jump_instr_type: - instruction_write_jumpInstr(bf, bi.jump); - break; - case syscall_instr_type: - instruction_write_syscallInstr(bf, bi.syscall); - break; - default: - bail_with_error("Unknown instruction type in instruction_write_bin_instr (%d)", - instruction_type(bi)); - break; - } -} - - -// Requires: bof is open for writing in binary -// Write the computational instruction ci to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_compInstr(BOFFILE bf, comp_instr_t ci) -{ - bin_instr_t bi; - bi.comp = ci; - assert(bi.comp.op == ci.op); - assert(bi.comp.rt == ci.rt); - assert(bi.comp.ot == ci.ot); - assert(bi.comp.rs == ci.rs); - assert(bi.comp.os == ci.os); - assert(bi.comp.func == ci.func); - assert(bi.comp.func != NOP_F || bi.comp.op == COMP_O); - write_bin_instr(bf, bi); -} - -// Requires: bof is open for writing in binary -// Write the other computational instruction oci to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_otherCompInstr(BOFFILE bf, other_comp_instr_t oci) -{ - bin_instr_t bi; - bi.othc = oci; - - assert(bi.othc.op == oci.op); - assert(bi.othc.reg == oci.reg); - assert(bi.othc.offset == oci.offset); - assert(bi.othc.arg == oci.arg); - assert(bi.othc.func == oci.func); - - write_bin_instr(bf, bi); -} - -// Requires: bof is open for writing in binary -// Write the system instruction si to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_syscallInstr(BOFFILE bf, syscall_instr_t si) -{ - bin_instr_t bi; - bi.syscall = si; - /* - assert(bi.syscall.op == OTHC_O); - assert(bi.syscall.reg == si.reg); - assert(bi.syscall.offset == si.offset); - assert(bi.syscall.code == si.code); - assert(bi.syscall.func == SYS_F); - */ - write_bin_instr(bf, bi); -} - -// Requires: bof is open for writing in binary -// Write the immediate instruction ii to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_uimmedInstr(BOFFILE bf, uimmed_instr_t ui) -{ - bin_instr_t bi; - bi.uimmed = ui; - /* - assert(bi.uimmed.op == op); - assert(bi.uimmed.reg == ui.reg); - assert(bi.uimmed.offset == ui.offset); - assert(bi.uimmed.uimmed == ui.uimmed); - */ - write_bin_instr(bf, bi); -} - -// Requires: bof is open for writing in binary -// Write the immediate instruction ii to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_immedInstr(BOFFILE bf, immed_instr_t ii) -{ - bin_instr_t bi; - bi.immed = ii; - /* - assert(bi.immed.op == op); - assert(bi.immed.reg == ii.reg); - assert(bi.immed.offset == ii.offset); - assert(bi.immed.immed == ii.immed); - */ - write_bin_instr(bf, bi); -} - -// Requires: bof is open for writing in binary -// Write the jump instruction ji with opcode op to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_jumpInstr(BOFFILE bf, jump_instr_t ji) -{ - bin_instr_t bi; - bi.jump = ji; - /* - assert(bi.jump.op == op); - assert(bi.jump.addr == ji.addr); - */ - write_bin_instr(bf, bi); -} - -// Return the assembly language name (mnemonic) for bi -const char *instruction_mnemonic(bin_instr_t bi) { - switch (bi.comp.op) { // pretending a type is needed to get the op field - case COMP_O: - return instruction_compFunc2name(bi); - break; - case OTHC_O: - return instruction_otherCompFunc2name(bi); - break; - case ADDI_O: - return "ADDI"; - break; - case ANDI_O: - return "ANDI"; - break; - case BORI_O: - return "BORI"; - break; - case NORI_O: - return "NORI"; - break; - case XORI_O: - return "XORI"; - break; - case BEQ_O: - return "BEQ"; - break; - case BGEZ_O: - return "BGEZ"; - break; - case BGTZ_O: - return "BGTZ"; - break; - case BLEZ_O: - return "BLEZ"; - break; - case BLTZ_O: - return "BLTZ"; - break; - case BNE_O: - return "BNE"; - break; - case JMPA_O: - return "JMPA"; - break; - case CALL_O: - return "CALL"; - break; - case RTN_O: - return "RTN"; - break; - default: - bail_with_error("Unknown op code (%d) in instruction_mnemonic!", - bi.immed.op); - return NULL; // should never happen - } - return NULL; // should never happen -} - -static char address_comment_buf[512]; - -// return a comment string of the form -// "# target is word address %u" -// that uses the formAddress function to get the proper address -static const char *instruction_formAddress_comment(address_type addr, - address_type a) -{ - address_type actual = machine_types_formAddress(addr, a); - sprintf(address_comment_buf, "# target is word address %u", - actual); - return strdup(address_comment_buf); -} - - -// Return a string containing the assembly language form of instr, -// which is found at address addr -const char *instruction_assembly_form(address_type addr, - bin_instr_t instr) -{ - char *buf = instr_buf; - - // put in the mnemonic for the instruction - int cwr = sprintf(buf, "%s ", instruction_mnemonic(instr)); - // point buf to the null char that was printed into instr_buf - buf += cwr; - - instr_type it = instruction_type(instr); - switch (it) { - case comp_instr_type: - switch (instr.comp.func) { - case NOP_F: - // no arguments for NOP! - break; - case ADD_F: case SUB_F: case CPW_F: - case AND_F: case BOR_F: case NOR_F: case XOR_F: - case SCA_F: case LWI_F: case NEG_F: - sprintf(buf, "%s, %hd, %s, %hd", - regname_get(instr.comp.rt), - instr.comp.ot, - regname_get(instr.comp.rs), - instr.comp.os); - break; - case CPR_F: - sprintf(buf, "%s, %s", - regname_get(instr.comp.rt), - regname_get(instr.comp.rs)); - break; - case LWR_F: - sprintf(buf, "%s, %s, %hd", - regname_get(instr.comp.rt), - regname_get(instr.comp.rs), - instr.comp.os); - break; - case SWR_F: - sprintf(buf, "%s, %hd, %s", - regname_get(instr.comp.rt), - instr.comp.ot, - regname_get(instr.comp.rs)); - break; - default: - bail_with_error("Unknown computational instruction function (%d) for mnemonic %s!", - instr.comp.func, buf); - break; - } - break; - case other_comp_instr_type: - assert(instr.othc.op == OTHC_O); - switch (instr.othc.func) { - case LIT_F: - sprintf(buf, "%s, %hd, %hd", regname_get(instr.othc.reg), - instr.othc.offset, instr.othc.arg); - break; - case ARI_F: case SRI_F: - sprintf(buf, "%s, %hd", regname_get(instr.othc.reg), - instr.othc.arg); - break; - case MUL_F: case DIV_F: case CFHI_F: case CFLO_F: case JMP_F: - case CSI_F: - sprintf(buf, "%s, %hd", regname_get(instr.othc.reg), - instr.othc.offset); - break; - case SLL_F: case SRL_F: - sprintf(buf, "%s, %hd, %hu", regname_get(instr.othc.reg), - instr.othc.offset, instr.othc.arg); - break; - case JREL_F: - sprintf(buf, "%hd\t%s", instr.othc.arg, - instruction_formAddress_comment(addr, - addr+instr.othc.arg)); - break; - default: - bail_with_error("Unknown other computational instruction function (%d)!", - instr.comp.func); - break; - } - break; - case immed_instr_type: - switch (instr.immed.op) { - case ADDI_O: - sprintf(buf, "%s, %hd, %hd", regname_get(instr.immed.reg), - instr.immed.offset, instr.immed.immed); - break; - case ANDI_O: case BORI_O: case NORI_O: case XORI_O: - sprintf(buf, "%s, %hd, 0x%hx", regname_get(instr.immed.reg), - instr.immed.offset, instr.immed.immed); - break; - case BEQ_O: case BGEZ_O: case BGTZ_O: - case BLEZ_O: case BLTZ_O: case BNE_O: - sprintf(buf, "%s, %hd, %hd\t%s", regname_get(instr.immed.reg), - instr.immed.offset, instr.immed.immed, - instruction_formAddress_comment(addr, - addr+instr.immed.immed)); - break; - default: - bail_with_error("Unknown immediate type instruction opcode (%d)!", - instr.immed.op); - break; - } - break; - case jump_instr_type: - switch (instr.jump.op) { - case JMPA_O: case CALL_O: - sprintf(buf, "%u\t%s", instr.jump.addr, - instruction_formAddress_comment(addr, instr.jump.addr)); - break; - case RTN_O: - // no arguments in this case - break; - default: - bail_with_error("Unknown jump type instruction opcode (%d)!", - instr.jump.op); - break; - } - break; - case syscall_instr_type: - switch (instr.syscall.code) { - case exit_sc: - sprintf(buf, "%hd", instr.syscall.offset); - break; - case print_str_sc: case print_int_sc: - case print_char_sc: case read_char_sc: - sprintf(buf, "%s, %hd", regname_get(instr.syscall.reg), - instr.syscall.offset); - break; - case start_tracing_sc: case stop_tracing_sc: - // no arguments, so nothing to do! - break; - } - break; - default: - bail_with_error("Unknown instruction type (%d) in instruction_assembly_form!", - it); - break; - } - - return instr_buf; -} - -// Requires: out is open and writable FILE -// print the header of the instruction output table on out -void instruction_print_table_heading(FILE *out) { - fprintf(out, "%s %s\n", "Address", "Instruction"); -} - -// Requires: out is an open FILE, and instr is found at address addr. -// Print addr on out, ": ", then the instruction's symbolic -// (assembly language) form, and finally a newline character (all on one line) -void instruction_print(FILE *out, address_type addr, bin_instr_t instr) { - fprintf(out, "%8u: %s\n", addr, instruction_assembly_form(addr, instr)); -} - -// Return the mnemonic for the given system call code -const char *instruction_syscall_mnemonic(syscall_type code) -{ - switch (code) { - case exit_sc: - return "EXIT"; - break; - case print_str_sc: - return "PSTR"; - break; - case print_int_sc: - return "PINT"; - break; - case print_char_sc: - return "PCH"; - break; - case read_char_sc: - return "RCH"; - break; - case start_tracing_sc: - return "STRA"; - break; - case stop_tracing_sc: - return "NOTR"; - break; - default: - bail_with_error("Unknown code (%u) in instruction_syscall_mnemonic", - code); - return "NEVERHAPPENS"; - break; - } -} - -// Requires: instr is a SYSCALL instruction -// (i.e., instr.syscall.op == OTHC_O and instr.syscall.func == SYS_F). -// Return the code field that tells what kind of system call is being made -syscall_type instruction_syscall_number(bin_instr_t instr) { - assert(instr.syscall.op == OTHC_O && instr.syscall.func == SYS_F); - return instr.syscall.code; -} - -// Requires: bi is a computational instruction (bi.comp.op == COMP_O). -// Return a string giving the assembly language mnemonic for bi's operation -const char *instruction_compFunc2name(bin_instr_t bi) { - assert(bi.comp.op == COMP_O); - switch (bi.comp.func) { - case NOP_F: - return "NOP"; - break; - case ADD_F: - return "ADD"; - break; - case SUB_F: - return "SUB"; - break; - case CPW_F: - return "CPW"; - break; - case CPR_F: - return "CPR"; - break; - case AND_F: - return "AND"; - break; - case BOR_F: - return "BOR"; - break; - case NOR_F: - return "NOR"; - break; - case XOR_F: - return "XOR"; - break; - case LWR_F: - return "LWR"; - break; - case SWR_F: - return "SWR"; - break; - case SCA_F: - return "SCA"; - break; - case LWI_F: - return "LWI"; - break; - case NEG_F: - return "NEG"; - break; - default: - bail_with_error("Unknown function code (%d) in instruction_compFunc2name", - bi.comp.func); - break; - } - return NULL; // should never happen -} - -// Requires: bi is an other computational instruction (bi.othc.op == OTHC_O). -// Return a string giving the assembly language mnemonic for bi's operation -const char *instruction_otherCompFunc2name(bin_instr_t bi) { - assert(bi.othc.op == OTHC_O); - switch (bi.othc.func) { - case LIT_F: - return "LIT"; - break; - case ARI_F: - return "ARI"; - break; - case SRI_F: - return "SRI"; - break; - case MUL_F: - return "MUL"; - break; - case DIV_F: - return "DIV"; - break; - case CFHI_F: - return "CFHI"; - break; - case CFLO_F: - return "CFLO"; - break; - case SLL_F: - return "SLL"; - break; - case SRL_F: - return "SRL"; - break; - case JMP_F: - return "JMP"; - break; - case CSI_F: - return "CSI"; - break; - case JREL_F: - return "JREL"; - break; - case SYS_F: - return instruction_syscall_mnemonic(instruction_syscall_number(bi)); - break; - default: - bail_with_error("Unknown function code (%d) in instruction_otherCompFunc2name", - bi.comp.func); - break; - } - return NULL; // should never happen -} +// $Id: instruction.c,v 1.7 2024/11/10 21:09:43 leavens Exp $ +#include +#include +#include "bof.h" +#include "instruction.h" +#include "regname.h" +#include "utilities.h" +#include "machine_types.h" + +#define INSTR_BUF_SIZE 512 + +// the following declaration isn't in everywhere ... +extern char *strdup(const char *s); + +// space to hold one instruction's assembly language form +static char instr_buf[INSTR_BUF_SIZE]; + +// Return the instruction type of the given opcode +instr_type instruction_type(bin_instr_t i) { + switch (i.comp.op) { // need to pretend a type to read the op field + case COMP_O: + return comp_instr_type; + break; + case OTHC_O: + if (i.othc.func == SYS_F) { + return syscall_instr_type; + } else { + assert(i.othc.op != COMP_O); + assert(i.othc.func != NOP_F); + return other_comp_instr_type; + } + break; + case ADDI_O: case ANDI_O: case BORI_O: case NORI_O: case XORI_O: + case BEQ_O: case BGEZ_O: case BGTZ_O: case BLEZ_O: case BLTZ_O: + case BNE_O: + return immed_instr_type; + break; + case JMPA_O: case CALL_O: case RTN_O: + return jump_instr_type; + break; + default: + return error_instr_type; + break; + } +} + +// Requires: bof is open for reading in binary +// Read a single instruction (in binary) from bf and return it, +// but exit with an error if there is a problem. +bin_instr_t instruction_read(BOFFILE bf) +{ + bin_instr_t bi; + size_t rd = fread(&bi, sizeof(bi), 1, bf.fileptr); + if (rd != 1) { + bail_with_error("Cannot read instruction from %s (read %d instrs)", + bf.filename, rd); + } + return bi; +} + +// Requires: bf is open for writing in binary +// Write the given binary instruction to bf, +// but exit with an error if there is a problem. +static void write_bin_instr(BOFFILE bf, bin_instr_t i) +{ + size_t wr = fwrite(&i, sizeof(i), 1, bf.fileptr); + if (wr != 1) { + bail_with_error("Cannot write binary instr to %s", bf.filename); + } +} + +// Requires: bof is open for writing in binary +// Write the binary instruction bi to bf in binary, +// but exit with an error if there is a problem. +void instruction_write_bin_instr(BOFFILE bf, bin_instr_t bi) +{ + switch (instruction_type(bi)) { + case comp_instr_type: + instruction_write_compInstr(bf, bi.comp); + break; + case other_comp_instr_type: + instruction_write_otherCompInstr(bf, bi.othc); + break; + case immed_instr_type: + instruction_write_immedInstr(bf, bi.immed); + break; + case jump_instr_type: + instruction_write_jumpInstr(bf, bi.jump); + break; + case syscall_instr_type: + instruction_write_syscallInstr(bf, bi.syscall); + break; + default: + bail_with_error("Unknown instruction type in instruction_write_bin_instr (%d)", + instruction_type(bi)); + break; + } +} + + +// Requires: bof is open for writing in binary +// Write the computational instruction ci to bf in binary, +// but exit with an error if there is a problem. +void instruction_write_compInstr(BOFFILE bf, comp_instr_t ci) +{ + bin_instr_t bi; + bi.comp = ci; + assert(bi.comp.op == ci.op); + assert(bi.comp.rt == ci.rt); + assert(bi.comp.ot == ci.ot); + assert(bi.comp.rs == ci.rs); + assert(bi.comp.os == ci.os); + assert(bi.comp.func == ci.func); + assert(bi.comp.func != NOP_F || bi.comp.op == COMP_O); + write_bin_instr(bf, bi); +} + +// Requires: bof is open for writing in binary +// Write the other computational instruction oci to bf in binary, +// but exit with an error if there is a problem. +void instruction_write_otherCompInstr(BOFFILE bf, other_comp_instr_t oci) +{ + bin_instr_t bi; + bi.othc = oci; + + assert(bi.othc.op == oci.op); + assert(bi.othc.reg == oci.reg); + assert(bi.othc.offset == oci.offset); + assert(bi.othc.arg == oci.arg); + assert(bi.othc.func == oci.func); + + write_bin_instr(bf, bi); +} + +// Requires: bof is open for writing in binary +// Write the system instruction si to bf in binary, +// but exit with an error if there is a problem. +void instruction_write_syscallInstr(BOFFILE bf, syscall_instr_t si) +{ + bin_instr_t bi; + bi.syscall = si; + /* + assert(bi.syscall.op == OTHC_O); + assert(bi.syscall.reg == si.reg); + assert(bi.syscall.offset == si.offset); + assert(bi.syscall.code == si.code); + assert(bi.syscall.func == SYS_F); + */ + write_bin_instr(bf, bi); +} + +// Requires: bof is open for writing in binary +// Write the immediate instruction ii to bf in binary, +// but exit with an error if there is a problem. +void instruction_write_uimmedInstr(BOFFILE bf, uimmed_instr_t ui) +{ + bin_instr_t bi; + bi.uimmed = ui; + /* + assert(bi.uimmed.op == op); + assert(bi.uimmed.reg == ui.reg); + assert(bi.uimmed.offset == ui.offset); + assert(bi.uimmed.uimmed == ui.uimmed); + */ + write_bin_instr(bf, bi); +} + +// Requires: bof is open for writing in binary +// Write the immediate instruction ii to bf in binary, +// but exit with an error if there is a problem. +void instruction_write_immedInstr(BOFFILE bf, immed_instr_t ii) +{ + bin_instr_t bi; + bi.immed = ii; + /* + assert(bi.immed.op == op); + assert(bi.immed.reg == ii.reg); + assert(bi.immed.offset == ii.offset); + assert(bi.immed.immed == ii.immed); + */ + write_bin_instr(bf, bi); +} + +// Requires: bof is open for writing in binary +// Write the jump instruction ji with opcode op to bf in binary, +// but exit with an error if there is a problem. +void instruction_write_jumpInstr(BOFFILE bf, jump_instr_t ji) +{ + bin_instr_t bi; + bi.jump = ji; + /* + assert(bi.jump.op == op); + assert(bi.jump.addr == ji.addr); + */ + write_bin_instr(bf, bi); +} + +// Return the assembly language name (mnemonic) for bi +const char *instruction_mnemonic(bin_instr_t bi) { + switch (bi.comp.op) { // pretending a type is needed to get the op field + case COMP_O: + return instruction_compFunc2name(bi); + break; + case OTHC_O: + return instruction_otherCompFunc2name(bi); + break; + case ADDI_O: + return "ADDI"; + break; + case ANDI_O: + return "ANDI"; + break; + case BORI_O: + return "BORI"; + break; + case NORI_O: + return "NORI"; + break; + case XORI_O: + return "XORI"; + break; + case BEQ_O: + return "BEQ"; + break; + case BGEZ_O: + return "BGEZ"; + break; + case BGTZ_O: + return "BGTZ"; + break; + case BLEZ_O: + return "BLEZ"; + break; + case BLTZ_O: + return "BLTZ"; + break; + case BNE_O: + return "BNE"; + break; + case JMPA_O: + return "JMPA"; + break; + case CALL_O: + return "CALL"; + break; + case RTN_O: + return "RTN"; + break; + default: + bail_with_error("Unknown op code (%d) in instruction_mnemonic!", + bi.immed.op); + return NULL; // should never happen + } + return NULL; // should never happen +} + +static char address_comment_buf[512]; + +// return a comment string of the form +// "# target is word address %u" +// that uses the formAddress function to get the proper address +static const char *instruction_formAddress_comment(address_type addr, + address_type a) +{ + address_type actual = machine_types_formAddress(addr, a); + sprintf(address_comment_buf, "# target is word address %u", + actual); + return strdup(address_comment_buf); +} + + +// Return a string containing the assembly language form of instr, +// which is found at address addr +const char *instruction_assembly_form(address_type addr, + bin_instr_t instr) +{ + char *buf = instr_buf; + + // put in the mnemonic for the instruction + int cwr = sprintf(buf, "%s ", instruction_mnemonic(instr)); + // point buf to the null char that was printed into instr_buf + buf += cwr; + + instr_type it = instruction_type(instr); + switch (it) { + case comp_instr_type: + switch (instr.comp.func) { + case NOP_F: + // no arguments for NOP! + break; + case ADD_F: case SUB_F: case CPW_F: + case AND_F: case BOR_F: case NOR_F: case XOR_F: + case SCA_F: case LWI_F: case NEG_F: + sprintf(buf, "%s, %hd, %s, %hd", + regname_get(instr.comp.rt), + instr.comp.ot, + regname_get(instr.comp.rs), + instr.comp.os); + break; + case CPR_F: + sprintf(buf, "%s, %s", + regname_get(instr.comp.rt), + regname_get(instr.comp.rs)); + break; + case LWR_F: + sprintf(buf, "%s, %s, %hd", + regname_get(instr.comp.rt), + regname_get(instr.comp.rs), + instr.comp.os); + break; + case SWR_F: + sprintf(buf, "%s, %hd, %s", + regname_get(instr.comp.rt), + instr.comp.ot, + regname_get(instr.comp.rs)); + break; + default: + bail_with_error("Unknown computational instruction function (%d) for mnemonic %s!", + instr.comp.func, buf); + break; + } + break; + case other_comp_instr_type: + assert(instr.othc.op == OTHC_O); + switch (instr.othc.func) { + case LIT_F: + sprintf(buf, "%s, %hd, %hd", regname_get(instr.othc.reg), + instr.othc.offset, instr.othc.arg); + break; + case ARI_F: case SRI_F: + sprintf(buf, "%s, %hd", regname_get(instr.othc.reg), + instr.othc.arg); + break; + case MUL_F: case DIV_F: case CFHI_F: case CFLO_F: case JMP_F: + case CSI_F: + sprintf(buf, "%s, %hd", regname_get(instr.othc.reg), + instr.othc.offset); + break; + case SLL_F: case SRL_F: + sprintf(buf, "%s, %hd, %hu", regname_get(instr.othc.reg), + instr.othc.offset, instr.othc.arg); + break; + case JREL_F: + sprintf(buf, "%hd\t%s", instr.othc.arg, + instruction_formAddress_comment(addr, + addr+instr.othc.arg)); + break; + default: + bail_with_error("Unknown other computational instruction function (%d)!", + instr.comp.func); + break; + } + break; + case immed_instr_type: + switch (instr.immed.op) { + case ADDI_O: + sprintf(buf, "%s, %hd, %hd", regname_get(instr.immed.reg), + instr.immed.offset, instr.immed.immed); + break; + case ANDI_O: case BORI_O: case NORI_O: case XORI_O: + sprintf(buf, "%s, %hd, 0x%hx", regname_get(instr.immed.reg), + instr.immed.offset, instr.immed.immed); + break; + case BEQ_O: case BGEZ_O: case BGTZ_O: + case BLEZ_O: case BLTZ_O: case BNE_O: + sprintf(buf, "%s, %hd, %hd\t%s", regname_get(instr.immed.reg), + instr.immed.offset, instr.immed.immed, + instruction_formAddress_comment(addr, + addr+instr.immed.immed)); + break; + default: + bail_with_error("Unknown immediate type instruction opcode (%d)!", + instr.immed.op); + break; + } + break; + case jump_instr_type: + switch (instr.jump.op) { + case JMPA_O: case CALL_O: + sprintf(buf, "%u\t%s", instr.jump.addr, + instruction_formAddress_comment(addr, instr.jump.addr)); + break; + case RTN_O: + // no arguments in this case + break; + default: + bail_with_error("Unknown jump type instruction opcode (%d)!", + instr.jump.op); + break; + } + break; + case syscall_instr_type: + switch (instr.syscall.code) { + case exit_sc: + sprintf(buf, "%hd", instr.syscall.offset); + break; + case print_str_sc: case print_int_sc: + case print_char_sc: case read_char_sc: + sprintf(buf, "%s, %hd", regname_get(instr.syscall.reg), + instr.syscall.offset); + break; + case start_tracing_sc: case stop_tracing_sc: + // no arguments, so nothing to do! + break; + } + break; + default: + bail_with_error("Unknown instruction type (%d) in instruction_assembly_form!", + it); + break; + } + + return instr_buf; +} + +// Requires: out is open and writable FILE +// print the header of the instruction output table on out +void instruction_print_table_heading(FILE *out) { + fprintf(out, "%s %s\n", "Address", "Instruction"); +} + +// Requires: out is an open FILE, and instr is found at address addr. +// Print addr on out, ": ", then the instruction's symbolic +// (assembly language) form, and finally a newline character (all on one line) +void instruction_print(FILE *out, address_type addr, bin_instr_t instr) { + fprintf(out, "%8u: %s\n", addr, instruction_assembly_form(addr, instr)); +} + +// Return the mnemonic for the given system call code +const char *instruction_syscall_mnemonic(syscall_type code) +{ + switch (code) { + case exit_sc: + return "EXIT"; + break; + case print_str_sc: + return "PSTR"; + break; + case print_int_sc: + return "PINT"; + break; + case print_char_sc: + return "PCH"; + break; + case read_char_sc: + return "RCH"; + break; + case start_tracing_sc: + return "STRA"; + break; + case stop_tracing_sc: + return "NOTR"; + break; + default: + bail_with_error("Unknown code (%u) in instruction_syscall_mnemonic", + code); + return "NEVERHAPPENS"; + break; + } +} + +// Requires: instr is a SYSCALL instruction +// (i.e., instr.syscall.op == OTHC_O and instr.syscall.func == SYS_F). +// Return the code field that tells what kind of system call is being made +syscall_type instruction_syscall_number(bin_instr_t instr) { + assert(instr.syscall.op == OTHC_O && instr.syscall.func == SYS_F); + return instr.syscall.code; +} + +// Requires: bi is a computational instruction (bi.comp.op == COMP_O). +// Return a string giving the assembly language mnemonic for bi's operation +const char *instruction_compFunc2name(bin_instr_t bi) { + assert(bi.comp.op == COMP_O); + switch (bi.comp.func) { + case NOP_F: + return "NOP"; + break; + case ADD_F: + return "ADD"; + break; + case SUB_F: + return "SUB"; + break; + case CPW_F: + return "CPW"; + break; + case CPR_F: + return "CPR"; + break; + case AND_F: + return "AND"; + break; + case BOR_F: + return "BOR"; + break; + case NOR_F: + return "NOR"; + break; + case XOR_F: + return "XOR"; + break; + case LWR_F: + return "LWR"; + break; + case SWR_F: + return "SWR"; + break; + case SCA_F: + return "SCA"; + break; + case LWI_F: + return "LWI"; + break; + case NEG_F: + return "NEG"; + break; + default: + bail_with_error("Unknown function code (%d) in instruction_compFunc2name", + bi.comp.func); + break; + } + return NULL; // should never happen +} + +// Requires: bi is an other computational instruction (bi.othc.op == OTHC_O). +// Return a string giving the assembly language mnemonic for bi's operation +const char *instruction_otherCompFunc2name(bin_instr_t bi) { + assert(bi.othc.op == OTHC_O); + switch (bi.othc.func) { + case LIT_F: + return "LIT"; + break; + case ARI_F: + return "ARI"; + break; + case SRI_F: + return "SRI"; + break; + case MUL_F: + return "MUL"; + break; + case DIV_F: + return "DIV"; + break; + case CFHI_F: + return "CFHI"; + break; + case CFLO_F: + return "CFLO"; + break; + case SLL_F: + return "SLL"; + break; + case SRL_F: + return "SRL"; + break; + case JMP_F: + return "JMP"; + break; + case CSI_F: + return "CSI"; + break; + case JREL_F: + return "JREL"; + break; + case SYS_F: + return instruction_syscall_mnemonic(instruction_syscall_number(bi)); + break; + default: + bail_with_error("Unknown function code (%d) in instruction_otherCompFunc2name", + bi.comp.func); + break; + } + return NULL; // should never happen +} diff --git a/instruction.h b/FromGithub/instruction.h old mode 100755 new mode 100644 similarity index 97% rename from instruction.h rename to FromGithub/instruction.h index 0cc03c6..14c0ce7 --- a/instruction.h +++ b/FromGithub/instruction.h @@ -1,178 +1,178 @@ -// $Id: instruction.h,v 1.5 2024/11/10 21:09:43 leavens Exp $ -#ifndef _INSTRUCTION_H -#define _INSTRUCTION_H -#include -#include -#include "machine_types.h" -#include "bof.h" - -// op codes in binary instructions for the SSM -typedef enum {COMP_O = 0, OTHC_O = 1, ADDI_O = 2, ANDI_O = 3, BORI_O = 4, - NORI_O = 5, XORI_O = 6, - BEQ_O = 7, BGEZ_O = 8, BGTZ_O = 9, BLEZ_O = 10, BLTZ_O = 11, - BNE_O = 12, JMPA_O = 13, CALL_O = 14, RTN_O = 15 - } op_code; - -// function codes in binary instructions for the SSM (when opcode is 0) -typedef enum {NOP_F = 0, ADD_F = 1, SUB_F = 2, CPW_F = 3, CPR_F = 4, - AND_F = 5, BOR_F = 6, NOR_F = 7, XOR_F = 8, - LWR_F = 9, SWR_F = 10, SCA_F = 11, LWI_F = 12, NEG_F = 13 - } func0_code; - -// function codes in binary instructions for the SSM (when opcode is 1) -typedef enum {LIT_F = 1, ARI_F = 2, SRI_F = 3, MUL_F = 4, DIV_F = 5, - CFHI_F = 6, CFLO_F = 7, SLL_F = 8, SRL_F = 9, JMP_F = 10, - CSI_F = 11, JREL_F = 12, SYS_F = 15 - } func1_code; - -// instruction types (each is a binary instruction format) -typedef enum {comp_instr_type, other_comp_instr_type, - immed_instr_type, jump_instr_type, syscall_instr_type, - error_instr_type - } instr_type; - -// system calls -typedef enum {exit_sc = 1, print_str_sc = 2, print_int_sc = 3, - print_char_sc = 4, read_char_sc = 5, - start_tracing_sc = 2046, stop_tracing_sc = 2047 -} syscall_type; - -// computational type instructions, with opcode 0 -typedef struct { - opcode_type op : 4; - reg_num_type rt : 3; // target register - offset_type ot : 9; // offset from target register - reg_num_type rs : 3; // source register - offset_type os : 9; // offset from source register - func_type func : 4; -} comp_instr_t; - -// other computational type instructions, with opcode 1, except system calls -typedef struct { - opcode_type op : 4; - reg_num_type reg : 3; - offset_type offset : 9; - arg_type arg : 12; - func_type func : 4; -} other_comp_instr_t; - -// system call instructions, with op field 1 and func field 15 -typedef struct { - opcode_type op : 4; - reg_num_type reg : 3; - offset_type offset : 9; - syscall_type code : 12; - func_type func : 4; -} syscall_instr_t; - -// immediate operand type instructions -// with signed immediate operands -typedef struct { - opcode_type op : 4; - reg_num_type reg : 3; - offset_type offset : 9; - immediate_type immed : 16; -} immed_instr_t; - -// immediate operand type instructions -// with unsigned immediate operands -typedef struct { - opcode_type op : 4; - reg_num_type reg : 3; - offset_type offset : 9; - uimmed_type uimmed : 16; -} uimmed_instr_t; - -// jump type instructions -typedef struct { - opcode_type op : 4; - address_type addr : 28; -} jump_instr_t; - -// binary instructions of any type -typedef union { - comp_instr_t comp; - other_comp_instr_t othc; - syscall_instr_t syscall; - immed_instr_t immed; - uimmed_instr_t uimmed; - jump_instr_t jump; -} bin_instr_t; - -// Return the type of the binary instruction given -extern instr_type instruction_type(bin_instr_t i); - -// Requires: bof is open for reading in binary -// Read a single instruction (in binary) from bf and return it, -// but exit with an error if there is a problem. -extern bin_instr_t instruction_read(BOFFILE bf); - -// Requires: bof is open for writing in binary -// Write the binary instruction bi to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_bin_instr(BOFFILE bf, bin_instr_t bi); - -// Requires: bof is open for writing in binary -// Write the computational instruction oci to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_compInstr(BOFFILE bf, comp_instr_t oci); - -// Requires: bof is open for writing in binary -// Write the other computational instruction oci to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_otherCompInstr(BOFFILE bf, other_comp_instr_t oci); - -// Requires: bof is open for writing in binary -// Write the system instruction si to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_syscallInstr(BOFFILE bf, syscall_instr_t si); - -// Requires: bof is open for writing in binary -// Write the immediate instruction ii with opcode op to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_immedInstr(BOFFILE bf, immed_instr_t ii); - -// Requires: bof is open for writing in binary -// Write the immediate instruction ii with opcode op to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_uimmedInstr(BOFFILE bf, uimmed_instr_t ii); - -// Requires: bof is open for writing in binary -// Write the jump instruction ji with opcode op to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_jumpInstr(BOFFILE bf, jump_instr_t ji); - -// Return the assembly language name (mnemonic) for bi -extern const char *instruction_mnemonic(bin_instr_t bi); - -// Return a string containing the assembly language form of instr, -// which is found at address addr -extern const char *instruction_assembly_form(address_type addr, - bin_instr_t instr); - -// Requires: out is open and writable FILE -// print the header of the instruction output table on out -extern void instruction_print_table_heading(FILE *out); - -// Requires: out is an open FILE, and instr is found at address addr. -// Print addr on out, ": ", then the instruction's symbolic -// (assembly language) form, and finally a newline character (all on one line) -extern void instruction_print(FILE *out, address_type addr, bin_instr_t instr); - -// Return the mnemonic for the given system call code -extern const char *instruction_syscall_mnemonic(unsigned int code); - -// Requires: instr is a SYSCALL instruction -// (i.e., instr.syscall.op == OTHC_O and instr.syscall.func == SYS_F). -// Return the code field that tells what kind of system call is being made -extern syscall_type instruction_syscall_number(bin_instr_t instr); - -// Requires: bi is a computational instruction (bi.comp.op == COMP_O). -// Return a string giving the assembly language mnemonic for bi's operation -extern const char *instruction_compFunc2name(bin_instr_t bi); - -// Requires: bi is an other computational instruction (bi.othc.op == OTHC_O). -// Return a string giving the assembly language mnemonic for bi's operation -extern const char *instruction_otherCompFunc2name(bin_instr_t bi); - -#endif +// $Id: instruction.h,v 1.5 2024/11/10 21:09:43 leavens Exp $ +#ifndef _INSTRUCTION_H +#define _INSTRUCTION_H +#include +#include +#include "machine_types.h" +#include "bof.h" + +// op codes in binary instructions for the SSM +typedef enum {COMP_O = 0, OTHC_O = 1, ADDI_O = 2, ANDI_O = 3, BORI_O = 4, + NORI_O = 5, XORI_O = 6, + BEQ_O = 7, BGEZ_O = 8, BGTZ_O = 9, BLEZ_O = 10, BLTZ_O = 11, + BNE_O = 12, JMPA_O = 13, CALL_O = 14, RTN_O = 15 + } op_code; + +// function codes in binary instructions for the SSM (when opcode is 0) +typedef enum {NOP_F = 0, ADD_F = 1, SUB_F = 2, CPW_F = 3, CPR_F = 4, + AND_F = 5, BOR_F = 6, NOR_F = 7, XOR_F = 8, + LWR_F = 9, SWR_F = 10, SCA_F = 11, LWI_F = 12, NEG_F = 13 + } func0_code; + +// function codes in binary instructions for the SSM (when opcode is 1) +typedef enum {LIT_F = 1, ARI_F = 2, SRI_F = 3, MUL_F = 4, DIV_F = 5, + CFHI_F = 6, CFLO_F = 7, SLL_F = 8, SRL_F = 9, JMP_F = 10, + CSI_F = 11, JREL_F = 12, SYS_F = 15 + } func1_code; + +// instruction types (each is a binary instruction format) +typedef enum {comp_instr_type, other_comp_instr_type, + immed_instr_type, jump_instr_type, syscall_instr_type, + error_instr_type + } instr_type; + +// system calls +typedef enum {exit_sc = 1, print_str_sc = 2, print_int_sc = 3, + print_char_sc = 4, read_char_sc = 5, + start_tracing_sc = 2046, stop_tracing_sc = 2047 +} syscall_type; + +// computational type instructions, with opcode 0 +typedef struct { + opcode_type op : 4; + reg_num_type rt : 3; // target register + offset_type ot : 9; // offset from target register + reg_num_type rs : 3; // source register + offset_type os : 9; // offset from source register + func_type func : 4; +} comp_instr_t; + +// other computational type instructions, with opcode 1, except system calls +typedef struct { + opcode_type op : 4; + reg_num_type reg : 3; + offset_type offset : 9; + arg_type arg : 12; + func_type func : 4; +} other_comp_instr_t; + +// system call instructions, with op field 1 and func field 15 +typedef struct { + opcode_type op : 4; + reg_num_type reg : 3; + offset_type offset : 9; + syscall_type code : 12; + func_type func : 4; +} syscall_instr_t; + +// immediate operand type instructions +// with signed immediate operands +typedef struct { + opcode_type op : 4; + reg_num_type reg : 3; + offset_type offset : 9; + immediate_type immed : 16; +} immed_instr_t; + +// immediate operand type instructions +// with unsigned immediate operands +typedef struct { + opcode_type op : 4; + reg_num_type reg : 3; + offset_type offset : 9; + uimmed_type uimmed : 16; +} uimmed_instr_t; + +// jump type instructions +typedef struct { + opcode_type op : 4; + address_type addr : 28; +} jump_instr_t; + +// binary instructions of any type +typedef union { + comp_instr_t comp; + other_comp_instr_t othc; + syscall_instr_t syscall; + immed_instr_t immed; + uimmed_instr_t uimmed; + jump_instr_t jump; +} bin_instr_t; + +// Return the type of the binary instruction given +extern instr_type instruction_type(bin_instr_t i); + +// Requires: bof is open for reading in binary +// Read a single instruction (in binary) from bf and return it, +// but exit with an error if there is a problem. +extern bin_instr_t instruction_read(BOFFILE bf); + +// Requires: bof is open for writing in binary +// Write the binary instruction bi to bf in binary, +// but exit with an error if there is a problem. +extern void instruction_write_bin_instr(BOFFILE bf, bin_instr_t bi); + +// Requires: bof is open for writing in binary +// Write the computational instruction oci to bf in binary, +// but exit with an error if there is a problem. +extern void instruction_write_compInstr(BOFFILE bf, comp_instr_t oci); + +// Requires: bof is open for writing in binary +// Write the other computational instruction oci to bf in binary, +// but exit with an error if there is a problem. +extern void instruction_write_otherCompInstr(BOFFILE bf, other_comp_instr_t oci); + +// Requires: bof is open for writing in binary +// Write the system instruction si to bf in binary, +// but exit with an error if there is a problem. +extern void instruction_write_syscallInstr(BOFFILE bf, syscall_instr_t si); + +// Requires: bof is open for writing in binary +// Write the immediate instruction ii with opcode op to bf in binary, +// but exit with an error if there is a problem. +extern void instruction_write_immedInstr(BOFFILE bf, immed_instr_t ii); + +// Requires: bof is open for writing in binary +// Write the immediate instruction ii with opcode op to bf in binary, +// but exit with an error if there is a problem. +extern void instruction_write_uimmedInstr(BOFFILE bf, uimmed_instr_t ii); + +// Requires: bof is open for writing in binary +// Write the jump instruction ji with opcode op to bf in binary, +// but exit with an error if there is a problem. +extern void instruction_write_jumpInstr(BOFFILE bf, jump_instr_t ji); + +// Return the assembly language name (mnemonic) for bi +extern const char *instruction_mnemonic(bin_instr_t bi); + +// Return a string containing the assembly language form of instr, +// which is found at address addr +extern const char *instruction_assembly_form(address_type addr, + bin_instr_t instr); + +// Requires: out is open and writable FILE +// print the header of the instruction output table on out +extern void instruction_print_table_heading(FILE *out); + +// Requires: out is an open FILE, and instr is found at address addr. +// Print addr on out, ": ", then the instruction's symbolic +// (assembly language) form, and finally a newline character (all on one line) +extern void instruction_print(FILE *out, address_type addr, bin_instr_t instr); + +// Return the mnemonic for the given system call code +extern const char *instruction_syscall_mnemonic(unsigned int code); + +// Requires: instr is a SYSCALL instruction +// (i.e., instr.syscall.op == OTHC_O and instr.syscall.func == SYS_F). +// Return the code field that tells what kind of system call is being made +extern syscall_type instruction_syscall_number(bin_instr_t instr); + +// Requires: bi is a computational instruction (bi.comp.op == COMP_O). +// Return a string giving the assembly language mnemonic for bi's operation +extern const char *instruction_compFunc2name(bin_instr_t bi); + +// Requires: bi is an other computational instruction (bi.othc.op == OTHC_O). +// Return a string giving the assembly language mnemonic for bi's operation +extern const char *instruction_otherCompFunc2name(bin_instr_t bi); + +#endif diff --git a/FromGithub/instruction.o b/FromGithub/instruction.o new file mode 100644 index 0000000..e8710a2 Binary files /dev/null and b/FromGithub/instruction.o differ diff --git a/lexer.c b/FromGithub/lexer.c old mode 100755 new mode 100644 similarity index 96% rename from lexer.c rename to FromGithub/lexer.c index 0763360..7a09526 --- a/lexer.c +++ b/FromGithub/lexer.c @@ -1,6 +1,6 @@ -/* $Id: lexer.c,v 1.6 2024/10/23 13:38:20 leavens Exp $ */ - -#include "lexer.h" - -// All the functions declared in lexer.h are -// defined in the user code section of spl_lexer.l +/* $Id: lexer.c,v 1.6 2024/10/23 13:38:20 leavens Exp $ */ + +#include "lexer.h" + +// All the functions declared in lexer.h are +// defined in the user code section of spl_lexer.l diff --git a/lexer.h b/FromGithub/lexer.h old mode 100755 new mode 100644 similarity index 96% rename from lexer.h rename to FromGithub/lexer.h index 006536b..6b8ed5f --- a/lexer.h +++ b/FromGithub/lexer.h @@ -1,39 +1,39 @@ -/* $Id: lexer.h,v 1.3 2024/10/23 13:38:20 leavens Exp $ */ -#ifndef _LEXER_H -#define _LEXER_H -#include - -// Requires: fname != NULL -// Requires: fname is the name of a readable file -// Initialize the lexer and start it reading -// from the given file name -extern void lexer_init(char *fname); - -// Return the next token in the input -extern int yylex(); - -// Return the name of the current file -extern const char *lexer_filename(); - -// Return the line number of the next token -extern unsigned int lexer_line(); - -// On standard output: -// Print a message about the file name of the lexer's input -// and then print a heading for the lexer's output. -extern void lexer_print_output_header(); - -// Have any errors been noted by the lexer? -extern bool lexer_has_errors(); - -// Print information about the token t to stdout -// followed by a newline -extern void lexer_print_token(int t, unsigned int tline, - const char *txt); - -/* Read all the tokens from the input file - * and print each token on standard output - * using the format in lexer_print_token */ -extern void lexer_output(); - -#endif +/* $Id: lexer.h,v 1.3 2024/10/23 13:38:20 leavens Exp $ */ +#ifndef _LEXER_H +#define _LEXER_H +#include + +// Requires: fname != NULL +// Requires: fname is the name of a readable file +// Initialize the lexer and start it reading +// from the given file name +extern void lexer_init(char *fname); + +// Return the next token in the input +extern int yylex(); + +// Return the name of the current file +extern const char *lexer_filename(); + +// Return the line number of the next token +extern unsigned int lexer_line(); + +// On standard output: +// Print a message about the file name of the lexer's input +// and then print a heading for the lexer's output. +extern void lexer_print_output_header(); + +// Have any errors been noted by the lexer? +extern bool lexer_has_errors(); + +// Print information about the token t to stdout +// followed by a newline +extern void lexer_print_token(int t, unsigned int tline, + const char *txt); + +/* Read all the tokens from the input file + * and print each token on standard output + * using the format in lexer_print_token */ +extern void lexer_output(); + +#endif diff --git a/lexer_utilities.c b/FromGithub/lexer_utilities.c old mode 100755 new mode 100644 similarity index 97% rename from lexer_utilities.c rename to FromGithub/lexer_utilities.c index b0f9ed6..c79e2d6 --- a/lexer_utilities.c +++ b/FromGithub/lexer_utilities.c @@ -1,8 +1,8 @@ -/* $Id: lexer_utilities.c,v 1.3 2024/11/13 14:08:23 leavens Exp $ */ -#include -#include -#include -#include "lexer_utilities.h" - -/* yyerror() is defined in spl_lexer.c (which is made from spl_lexer.l) */ -/* formatted_yyerror() is defined in utilities.c */ +/* $Id: lexer_utilities.c,v 1.3 2024/11/13 14:08:23 leavens Exp $ */ +#include +#include +#include +#include "lexer_utilities.h" + +/* yyerror() is defined in spl_lexer.c (which is made from spl_lexer.l) */ +/* formatted_yyerror() is defined in utilities.c */ diff --git a/lexer_utilities.h b/FromGithub/lexer_utilities.h old mode 100755 new mode 100644 similarity index 97% rename from lexer_utilities.h rename to FromGithub/lexer_utilities.h index 530dca4..64e10c3 --- a/lexer_utilities.h +++ b/FromGithub/lexer_utilities.h @@ -1,15 +1,15 @@ -/* $Id: lexer_utilities.h,v 1.1 2023/11/13 05:13:55 leavens Exp $ */ -#ifndef _LEXER_UTILITIES_H -#define _LEXER_UTILITIES_H - -// Report a syntax error on the current line on stderr. -// The output looks like: the filename, ":", the lexer's current line number, -// ": ", and then msg. -extern void yyerror(const char *filename, const char *msg); - -// Call yyerror to print an error message on stderr -// starting with the filename, ":", the lexer's current line number, ": ", -// and then the formatted message (as in sprintf) -extern void formatted_yyerror(const char *filename, const char *fmt, ...); - -#endif +/* $Id: lexer_utilities.h,v 1.1 2023/11/13 05:13:55 leavens Exp $ */ +#ifndef _LEXER_UTILITIES_H +#define _LEXER_UTILITIES_H + +// Report a syntax error on the current line on stderr. +// The output looks like: the filename, ":", the lexer's current line number, +// ": ", and then msg. +extern void yyerror(const char *filename, const char *msg); + +// Call yyerror to print an error message on stderr +// starting with the filename, ":", the lexer's current line number, ": ", +// and then the formatted message (as in sprintf) +extern void formatted_yyerror(const char *filename, const char *fmt, ...); + +#endif diff --git a/FromGithub/lexer_utilities.o b/FromGithub/lexer_utilities.o new file mode 100644 index 0000000..09864d7 Binary files /dev/null and b/FromGithub/lexer_utilities.o differ diff --git a/lexical_address.c b/FromGithub/lexical_address.c old mode 100755 new mode 100644 similarity index 97% rename from lexical_address.c rename to FromGithub/lexical_address.c index 4215fec..e71fe4f --- a/lexical_address.c +++ b/FromGithub/lexical_address.c @@ -1,28 +1,28 @@ -/* $Id: lexical_address.c,v 1.3 2023/11/13 05:13:56 leavens Exp $ */ -#include "lexical_address.h" -#include "utilities.h" - -// Allocate and return a (fresh) lexical address -// where the levelsOutwards field is levelsOut -// and the offsetInAR field is the byte offset in the AR -lexical_address *lexical_address_create(unsigned int levelsOut, - unsigned int offset) -{ - lexical_address *ret = (lexical_address *) malloc(sizeof(lexical_address)); - if (ret == NULL) { - bail_with_error("No space to create a lexical_address!"); - } - ret->levelsOutward = levelsOut; - ret->offsetInAR = offset; - return ret; -} - -// Requires: out is not NULL and is open for writing -// Requires: la is not NULL -// Print the lexical address la in the form "(l,o)", -// where l is la->levelsOutwards and o is la->offsetInAR. -// Note: no newline or other spacing is added. -extern void lexical_address_print(FILE *out, lexical_address *la) -{ - fprintf(out, "(%d,%d)", la->levelsOutward, la->offsetInAR); -} +/* $Id: lexical_address.c,v 1.3 2023/11/13 05:13:56 leavens Exp $ */ +#include "lexical_address.h" +#include "utilities.h" + +// Allocate and return a (fresh) lexical address +// where the levelsOutwards field is levelsOut +// and the offsetInAR field is the byte offset in the AR +lexical_address *lexical_address_create(unsigned int levelsOut, + unsigned int offset) +{ + lexical_address *ret = (lexical_address *) malloc(sizeof(lexical_address)); + if (ret == NULL) { + bail_with_error("No space to create a lexical_address!"); + } + ret->levelsOutward = levelsOut; + ret->offsetInAR = offset; + return ret; +} + +// Requires: out is not NULL and is open for writing +// Requires: la is not NULL +// Print the lexical address la in the form "(l,o)", +// where l is la->levelsOutwards and o is la->offsetInAR. +// Note: no newline or other spacing is added. +extern void lexical_address_print(FILE *out, lexical_address *la) +{ + fprintf(out, "(%d,%d)", la->levelsOutward, la->offsetInAR); +} diff --git a/lexical_address.h b/FromGithub/lexical_address.h old mode 100755 new mode 100644 similarity index 96% rename from lexical_address.h rename to FromGithub/lexical_address.h index 973cd96..3ff456f --- a/lexical_address.h +++ b/FromGithub/lexical_address.h @@ -1,23 +1,23 @@ -/* $Id: lexical_address.h,v 1.3 2023/11/13 05:13:56 leavens Exp $ */ -#ifndef _LEXICAL_ADDRESS_H -#define _LEXICAL_ADDRESS_H - -#include -#include - -typedef struct { - unsigned int levelsOutward; - unsigned int offsetInAR; // in bytes -} lexical_address; - -// Allocate and return a (fresh) lexical address -// where the levelsOutwards field is levelsOut -// and the offsetInAR field is the byte offset in the AR -extern lexical_address *lexical_address_create(unsigned int levelsOut, - unsigned int offset); - -// Requires: out is not NULL and is open for writing -// Requires: la is not NULL -extern void lexical_address_print(FILE *out, lexical_address *la); - -#endif +/* $Id: lexical_address.h,v 1.3 2023/11/13 05:13:56 leavens Exp $ */ +#ifndef _LEXICAL_ADDRESS_H +#define _LEXICAL_ADDRESS_H + +#include +#include + +typedef struct { + unsigned int levelsOutward; + unsigned int offsetInAR; // in bytes +} lexical_address; + +// Allocate and return a (fresh) lexical address +// where the levelsOutwards field is levelsOut +// and the offsetInAR field is the byte offset in the AR +extern lexical_address *lexical_address_create(unsigned int levelsOut, + unsigned int offset); + +// Requires: out is not NULL and is open for writing +// Requires: la is not NULL +extern void lexical_address_print(FILE *out, lexical_address *la); + +#endif diff --git a/literal_table.c b/FromGithub/literal_table.c similarity index 100% rename from literal_table.c rename to FromGithub/literal_table.c diff --git a/literal_table.h b/FromGithub/literal_table.h similarity index 100% rename from literal_table.h rename to FromGithub/literal_table.h diff --git a/machine_types.c b/FromGithub/machine_types.c old mode 100755 new mode 100644 similarity index 96% rename from machine_types.c rename to FromGithub/machine_types.c index 5466e82..c370460 --- a/machine_types.c +++ b/FromGithub/machine_types.c @@ -1,100 +1,100 @@ -// $Id: machine_types.c,v 1.2 2024/10/23 13:38:20 leavens Exp $ -#include "machine_types.h" -#include "utilities.h" - -// Return the sign-extended equivalent of i -word_type machine_types_sgnExt(immediate_type i) { - return i; // preserves the value -} - -// Return the zero-extended equivalent of i -uword_type machine_types_zeroExt(immediate_type i) { - return (uword_type) i; -} - -// Return the offset given by o, -// which is the sign extension of o -word_type machine_types_formOffset(immediate_type o) { - return machine_types_sgnExt(o); -} - -// Return an address formed by concatenating the instruction address, a, -// with the high-order (4) bits of the PC. -address_type machine_types_formAddress(address_type PC, address_type a) { - return ((0xF0000000 & PC) | (0x0FFFFFF & a)); -} - -// Check that o can be represented as an offset field in an instruction -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_offset(word_type o) -{ - if (o > NINEBITSMAXSIGNED) { - bail_with_error("Offset is too large: %d", o); - } else if (o < NINEBITSMINSIGNED) { - bail_with_error("Offset is too small: %d", o); - } -} - -// Check that arg can be represented as an arg field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_arg(word_type arg) -{ - if (arg > TWELVEBITSMAXSIGNED) { - bail_with_error("12 bit argument is too large: %d", arg); - } else if (arg < TWELVEBITSMINSIGNED) { - bail_with_error("12 bit argument is too small: %d", arg); - } -} - -// Check that s can be represented as a shift field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_shift(word_type s) -{ - if (s > TWELVEBITSMAXUNSIGNED) { - bail_with_error("Shift is too large: %u", s); - } -} - -// Check that immed can be represented as a signed immediate field, -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_immed(word_type immed) -{ - if (immed > SIXTEENBITSMAXSIGNED) { - bail_with_error("Immediate argument is too large: %d", - immed); - } else if (immed < SIXTEENBITSMINSIGNED) { - bail_with_error("Immediate argument is too small: %d", - immed); - } -} - -// Check that arg can be represented as unsigned immediate field, -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_uimmed(word_type arg) -{ - if (arg > SIXTEENBITSMAXUNSIGNED) { - bail_with_error("Unsigned immediate argument is too large: %u", arg); - } -} - -// Check that addr can be represented as an address field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_addr(address_type addr) -{ - if (addr > TWENTYEIGHTBITSMAXUNSIGNED) { - bail_with_error("Address is too large: %u", addr); - } -} - -// Return the nearest multiple of BYTES_PER_WORD -// that is greater than or equal to n -int machine_types_round_up_to_wordsize(unsigned int n) -{ - int rem = n % BYTES_PER_WORD; - if (rem == 0) { - return n; - } else { - // assert(((n + (BYTES_PER_WORD - rem)) % BYTES_PER_WORD) == 0); - return n + (BYTES_PER_WORD - rem); - } -} +// $Id: machine_types.c,v 1.2 2024/10/23 13:38:20 leavens Exp $ +#include "machine_types.h" +#include "utilities.h" + +// Return the sign-extended equivalent of i +word_type machine_types_sgnExt(immediate_type i) { + return i; // preserves the value +} + +// Return the zero-extended equivalent of i +uword_type machine_types_zeroExt(immediate_type i) { + return (uword_type) i; +} + +// Return the offset given by o, +// which is the sign extension of o +word_type machine_types_formOffset(immediate_type o) { + return machine_types_sgnExt(o); +} + +// Return an address formed by concatenating the instruction address, a, +// with the high-order (4) bits of the PC. +address_type machine_types_formAddress(address_type PC, address_type a) { + return ((0xF0000000 & PC) | (0x0FFFFFF & a)); +} + +// Check that o can be represented as an offset field in an instruction +// bail with an error message if not (so doesn't return if wrong) +void machine_types_check_fits_in_offset(word_type o) +{ + if (o > NINEBITSMAXSIGNED) { + bail_with_error("Offset is too large: %d", o); + } else if (o < NINEBITSMINSIGNED) { + bail_with_error("Offset is too small: %d", o); + } +} + +// Check that arg can be represented as an arg field in an instruction, +// bail with an error message if not (so doesn't return if wrong) +void machine_types_check_fits_in_arg(word_type arg) +{ + if (arg > TWELVEBITSMAXSIGNED) { + bail_with_error("12 bit argument is too large: %d", arg); + } else if (arg < TWELVEBITSMINSIGNED) { + bail_with_error("12 bit argument is too small: %d", arg); + } +} + +// Check that s can be represented as a shift field in an instruction, +// bail with an error message if not (so doesn't return if wrong) +void machine_types_check_fits_in_shift(word_type s) +{ + if (s > TWELVEBITSMAXUNSIGNED) { + bail_with_error("Shift is too large: %u", s); + } +} + +// Check that immed can be represented as a signed immediate field, +// bail with an error message if not (so doesn't return if wrong) +void machine_types_check_fits_in_immed(word_type immed) +{ + if (immed > SIXTEENBITSMAXSIGNED) { + bail_with_error("Immediate argument is too large: %d", + immed); + } else if (immed < SIXTEENBITSMINSIGNED) { + bail_with_error("Immediate argument is too small: %d", + immed); + } +} + +// Check that arg can be represented as unsigned immediate field, +// bail with an error message if not (so doesn't return if wrong) +void machine_types_check_fits_in_uimmed(word_type arg) +{ + if (arg > SIXTEENBITSMAXUNSIGNED) { + bail_with_error("Unsigned immediate argument is too large: %u", arg); + } +} + +// Check that addr can be represented as an address field in an instruction, +// bail with an error message if not (so doesn't return if wrong) +void machine_types_check_fits_in_addr(address_type addr) +{ + if (addr > TWENTYEIGHTBITSMAXUNSIGNED) { + bail_with_error("Address is too large: %u", addr); + } +} + +// Return the nearest multiple of BYTES_PER_WORD +// that is greater than or equal to n +int machine_types_round_up_to_wordsize(unsigned int n) +{ + int rem = n % BYTES_PER_WORD; + if (rem == 0) { + return n; + } else { + // assert(((n + (BYTES_PER_WORD - rem)) % BYTES_PER_WORD) == 0); + return n + (BYTES_PER_WORD - rem); + } +} diff --git a/machine_types.h b/FromGithub/machine_types.h old mode 100755 new mode 100644 similarity index 97% rename from machine_types.h rename to FromGithub/machine_types.h index 01bcd1c..3827a13 --- a/machine_types.h +++ b/FromGithub/machine_types.h @@ -1,94 +1,94 @@ -// $Id: machine_types.h,v 1.3 2024/10/23 13:38:20 leavens Exp $ -// Machine Types for the Simplified Stack Machine (SSM) -#ifndef _MACHINE_TYPES_H -#define _MACHINE_TYPES_H - -#define BYTES_PER_WORD 4 - -// operation codes -typedef unsigned short opcode_type; - -// registers encoded in instructions -typedef unsigned short reg_num_type; - -// offset values (which are signed) encoded in instructions -typedef short offset_type; - -// function codes in computational instructions -typedef unsigned short func_type; - -// argument values (signed) encoded in instructions -typedef short arg_type; - -// shift values encoded in other computational instructions -typedef unsigned short shift_type; - -// immediate operands encoded in instructions -typedef int immediate_type; - -// unsigned immediate operands in instructions -typedef unsigned int uimmed_type; - -// addresses, assuming ints are 32 bits -typedef unsigned int address_type; - -// machine words, assuming ints are 32 bits -typedef int word_type; - -// machine words, unsigned -typedef unsigned int uword_type; - -// bytes, assuming chars are 8 bits -typedef unsigned char byte_type; - -#define NINEBITSMAXSIGNED 0xff -#define NINEBITSMINSIGNED -512 -#define TWELVEBITSMAXSIGNED 0x7ff -#define TWELVEBITSMINSIGNED -0x800 -#define TWELVEBITSMAXUNSIGNED 0xfff -#define SIXTEENBITSMAXSIGNED 0777 -#define SIXTEENBITSMINSIGNED -01000 -#define SIXTEENBITSMAXUNSIGNED 0xffff -#define TWENTYEIGHTBITSMAXUNSIGNED 0xfffffff - -// Return the sign-extended equivalent of i -extern word_type machine_types_sgnExt(immediate_type i); - -// Return the zero-extended equivalent of i -extern uword_type machine_types_zeroExt(immediate_type i); - -// Return the offset given by o, -// which is the sign extension of o -extern word_type machine_types_formOffset(immediate_type o); - -// Return an address formed by concatenating the instruction address, a, -// with the high-order (4) bits of the PC. -extern address_type machine_types_formAddress(address_type PC, address_type a); - -// Check that o can be represented as an offset field in an instruction -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_offset(word_type o); - -// Check that arg can be represented as an arg field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_arg(word_type arg); - -// Check that arg can be represented as a shift field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_shift(word_type arg); - -// Check that immed can be represented as a signed immediate field, -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_immed(word_type immed); - -// Check that arg can be represented as unsigned immediate field, -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_uimmed(word_type arg); - -// Check that addr can be represented as an address field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_addr(address_type addr); - -// the following line is for the documentation -// ... -#endif +// $Id: machine_types.h,v 1.3 2024/10/23 13:38:20 leavens Exp $ +// Machine Types for the Simplified Stack Machine (SSM) +#ifndef _MACHINE_TYPES_H +#define _MACHINE_TYPES_H + +#define BYTES_PER_WORD 4 + +// operation codes +typedef unsigned short opcode_type; + +// registers encoded in instructions +typedef unsigned short reg_num_type; + +// offset values (which are signed) encoded in instructions +typedef short offset_type; + +// function codes in computational instructions +typedef unsigned short func_type; + +// argument values (signed) encoded in instructions +typedef short arg_type; + +// shift values encoded in other computational instructions +typedef unsigned short shift_type; + +// immediate operands encoded in instructions +typedef int immediate_type; + +// unsigned immediate operands in instructions +typedef unsigned int uimmed_type; + +// addresses, assuming ints are 32 bits +typedef unsigned int address_type; + +// machine words, assuming ints are 32 bits +typedef int word_type; + +// machine words, unsigned +typedef unsigned int uword_type; + +// bytes, assuming chars are 8 bits +typedef unsigned char byte_type; + +#define NINEBITSMAXSIGNED 0xff +#define NINEBITSMINSIGNED -512 +#define TWELVEBITSMAXSIGNED 0x7ff +#define TWELVEBITSMINSIGNED -0x800 +#define TWELVEBITSMAXUNSIGNED 0xfff +#define SIXTEENBITSMAXSIGNED 0777 +#define SIXTEENBITSMINSIGNED -01000 +#define SIXTEENBITSMAXUNSIGNED 0xffff +#define TWENTYEIGHTBITSMAXUNSIGNED 0xfffffff + +// Return the sign-extended equivalent of i +extern word_type machine_types_sgnExt(immediate_type i); + +// Return the zero-extended equivalent of i +extern uword_type machine_types_zeroExt(immediate_type i); + +// Return the offset given by o, +// which is the sign extension of o +extern word_type machine_types_formOffset(immediate_type o); + +// Return an address formed by concatenating the instruction address, a, +// with the high-order (4) bits of the PC. +extern address_type machine_types_formAddress(address_type PC, address_type a); + +// Check that o can be represented as an offset field in an instruction +// bail with an error message if not (so doesn't return if wrong) +extern void machine_types_check_fits_in_offset(word_type o); + +// Check that arg can be represented as an arg field in an instruction, +// bail with an error message if not (so doesn't return if wrong) +extern void machine_types_check_fits_in_arg(word_type arg); + +// Check that arg can be represented as a shift field in an instruction, +// bail with an error message if not (so doesn't return if wrong) +extern void machine_types_check_fits_in_shift(word_type arg); + +// Check that immed can be represented as a signed immediate field, +// bail with an error message if not (so doesn't return if wrong) +extern void machine_types_check_fits_in_immed(word_type immed); + +// Check that arg can be represented as unsigned immediate field, +// bail with an error message if not (so doesn't return if wrong) +extern void machine_types_check_fits_in_uimmed(word_type arg); + +// Check that addr can be represented as an address field in an instruction, +// bail with an error message if not (so doesn't return if wrong) +extern void machine_types_check_fits_in_addr(address_type addr); + +// the following line is for the documentation +// ... +#endif diff --git a/FromGithub/machine_types.o b/FromGithub/machine_types.o new file mode 100644 index 0000000..cd81590 Binary files /dev/null and b/FromGithub/machine_types.o differ diff --git a/parser.c b/FromGithub/parser.c old mode 100755 new mode 100644 similarity index 96% rename from parser.c rename to FromGithub/parser.c index 69bbb84..c63d114 --- a/parser.c +++ b/FromGithub/parser.c @@ -1,22 +1,22 @@ -/* $Id: parser.c,v 1.6 2023/11/13 14:08:44 leavens Exp $ */ -#include -#include -#include "lexer.h" -#include "parser.h" -#include "utilities.h" - -// Parse a PL/0 program from the given file, -// putting the AST into progast -extern int yyparse (char const *file_name); - -// Parse a PL/0 program using the tokens from the lexer, -// returning the program's AST -extern block_t parseProgram(char *file_name) -{ - lexer_init(file_name); - int rc = yyparse(file_name); - if (rc != 0) { - exit(rc); - } - return progast; -} +/* $Id: parser.c,v 1.6 2023/11/13 14:08:44 leavens Exp $ */ +#include +#include +#include "lexer.h" +#include "parser.h" +#include "utilities.h" + +// Parse a PL/0 program from the given file, +// putting the AST into progast +extern int yyparse (char const *file_name); + +// Parse a PL/0 program using the tokens from the lexer, +// returning the program's AST +extern block_t parseProgram(char *file_name) +{ + lexer_init(file_name); + int rc = yyparse(file_name); + if (rc != 0) { + exit(rc); + } + return progast; +} diff --git a/parser.h b/FromGithub/parser.h old mode 100755 new mode 100644 similarity index 96% rename from parser.h rename to FromGithub/parser.h index 02bd7ce..c20d3d7 --- a/parser.h +++ b/FromGithub/parser.h @@ -1,13 +1,13 @@ -/* $Id: parser.h,v 1.3 2023/11/13 14:08:44 leavens Exp $ */ -// This header file defines the externally-visible entry points to the parser -#ifndef _PARSER_H -#define _PARSER_H -#include "ast.h" - -extern block_t progast; - -// Parse a PL/0 program using the tokens from the lexer, -// returning the program's AST -extern block_t parseProgram(char *file_name); - -#endif +/* $Id: parser.h,v 1.3 2023/11/13 14:08:44 leavens Exp $ */ +// This header file defines the externally-visible entry points to the parser +#ifndef _PARSER_H +#define _PARSER_H +#include "ast.h" + +extern block_t progast; + +// Parse a PL/0 program using the tokens from the lexer, +// returning the program's AST +extern block_t parseProgram(char *file_name); + +#endif diff --git a/FromGithub/parser.o b/FromGithub/parser.o new file mode 100644 index 0000000..b97fd67 Binary files /dev/null and b/FromGithub/parser.o differ diff --git a/parser_types.h b/FromGithub/parser_types.h old mode 100755 new mode 100644 similarity index 95% rename from parser_types.h rename to FromGithub/parser_types.h index b98bc78..0e73bc6 --- a/parser_types.h +++ b/FromGithub/parser_types.h @@ -1,11 +1,11 @@ -/* $Id: parser_types.h,v 1.1 2023/11/13 05:13:59 leavens Exp $ */ -#ifndef _PARSER_TYPES_H -#define _PARSER_TYPES_H - -#include "ast.h" - -// The type of Bison's parser stack elements (parse values) -typedef AST YYSTYPE; -#define YYSTYPE_IS_DECLARED 1 - -#endif +/* $Id: parser_types.h,v 1.1 2023/11/13 05:13:59 leavens Exp $ */ +#ifndef _PARSER_TYPES_H +#define _PARSER_TYPES_H + +#include "ast.h" + +// The type of Bison's parser stack elements (parse values) +typedef AST YYSTYPE; +#define YYSTYPE_IS_DECLARED 1 + +#endif diff --git a/regname.c b/FromGithub/regname.c old mode 100755 new mode 100644 similarity index 96% rename from regname.c rename to FromGithub/regname.c index 545fdf4..a1ef0cc --- a/regname.c +++ b/FromGithub/regname.c @@ -1,12 +1,12 @@ -// $Id: regname.c,v 1.2 2024/10/23 13:38:20 leavens Exp $ -#include "regname.h" - -static const char *regnames[NUM_REGISTERS] = { - "$gp", "$sp", "$fp", "$r3", "$r4", "$r5", "$r6", "$ra" }; - -// requires 0 <= n && n < NUM_REGISTERS -// Return the standard symbolic name for n -const char *regname_get(reg_num_type n) -{ - return regnames[n]; -} +// $Id: regname.c,v 1.2 2024/10/23 13:38:20 leavens Exp $ +#include "regname.h" + +static const char *regnames[NUM_REGISTERS] = { + "$gp", "$sp", "$fp", "$r3", "$r4", "$r5", "$r6", "$ra" }; + +// requires 0 <= n && n < NUM_REGISTERS +// Return the standard symbolic name for n +const char *regname_get(reg_num_type n) +{ + return regnames[n]; +} diff --git a/regname.h b/FromGithub/regname.h old mode 100755 new mode 100644 similarity index 95% rename from regname.h rename to FromGithub/regname.h index 56fe926..fb7b5ab --- a/regname.h +++ b/FromGithub/regname.h @@ -1,18 +1,18 @@ -// $Id: regname.h,v 1.2 2024/10/23 13:38:20 leavens Exp $ -#ifndef _REGNAME_H -#define _REGNAME_H -#include "machine_types.h" - -#define NUM_REGISTERS 8 - -// some important register numbers in the ISA -#define GP 0 -#define SP 1 -#define FP 2 -#define RA 7 - -// requires 0 <= n && n < NUM_REGISTERS -// Return the standard symbolic name for n -extern const char *regname_get(reg_num_type n); -#endif - +// $Id: regname.h,v 1.2 2024/10/23 13:38:20 leavens Exp $ +#ifndef _REGNAME_H +#define _REGNAME_H +#include "machine_types.h" + +#define NUM_REGISTERS 8 + +// some important register numbers in the ISA +#define GP 0 +#define SP 1 +#define FP 2 +#define RA 7 + +// requires 0 <= n && n < NUM_REGISTERS +// Return the standard symbolic name for n +extern const char *regname_get(reg_num_type n); +#endif + diff --git a/FromGithub/regname.o b/FromGithub/regname.o new file mode 100644 index 0000000..90acec3 Binary files /dev/null and b/FromGithub/regname.o differ diff --git a/scope.c b/FromGithub/scope.c old mode 100755 new mode 100644 similarity index 96% rename from scope.c rename to FromGithub/scope.c index 5127d41..1eca6ac --- a/scope.c +++ b/FromGithub/scope.c @@ -1,121 +1,121 @@ -/* $Id: scope.c,v 1.5 2023/11/13 12:51:58 leavens Exp $ */ -#include -#include -#include -#include -#include "scope.h" -#include "utilities.h" - -// Allocate a fresh scope symbol table and return (a pointer to) it. -// Issues an error message (on stderr) if there is no space -// and exits with a failure error code in that case. -scope_t *scope_create() -{ - scope_t *new_s - = (scope_t *) malloc(sizeof(scope_t)); - if (new_s == NULL) { - bail_with_error("No space for new scope_t!"); - } - new_s->size = 0; - new_s->loc_count = 0; - for (int j = 0; j < MAX_SCOPE_SIZE; j++) { - new_s->entries[j] = NULL; - } - return new_s; -} - -// Return the number of constant and variables declarations -// that have been added to this scope. -extern unsigned int scope_loc_count(scope_t *s) -{ - return s->loc_count; -} - -// Return the current scope's size (number of declared ids). -unsigned int scope_size(scope_t *s) -{ - return s->size; -} - -// Is the current scope full? -bool scope_full(scope_t *s) -{ - return scope_size(s) >= MAX_SCOPE_SIZE; -} - -// Requires: assoc != NULL && !scope_full() && !scope_defined(assoc->id); -// Add an association from the given name to the given id attributes -// in the current scope. -// If assoc->attrs->kind != procedure_idk, -// then this stores the scope_count value into assoc->attrs->offset_count -// and then increases loc_count by 1. -static void scope_add(scope_t *s, scope_assoc_t *assoc) -{ - // assert(assoc != NULL); - // assert(!scope_full()); - // assert(!scope_defined(assoc->id)); - if (assoc->attrs->kind != procedure_idk) { - (assoc->attrs->offset_count) = (s->loc_count)++; - } - s->entries[(s->size)++] = assoc; - // fprintf(stderr, "assoc->attrs->offset_count is %d\n", - // assoc->attrs->offset_count); -} - -// Requires: !scope_defined(name) && attrs != NULL; -// Modify the current scope symbol table to -// add an association from the given name to the given id_attrs attrs, -// and if attrs->kind != procedure, -// then this stores the loc_count value into attrs->offset_count -// and then increases the loc_count for this scope by 1. -void scope_insert(scope_t *s, const char *name, id_attrs *attrs) -{ - // assert(!scope_defined(name)); - // assert(attrs != NULL); - // debug_print("Running scope_insert for name "%s\"\n", name); - scope_assoc_t *new_assoc = malloc(sizeof(scope_assoc_t)); - if (new_assoc == NULL) { - bail_with_error("No space for association!"); - } - new_assoc->id = name; - new_assoc->attrs = attrs; - scope_add(s, new_assoc); -} - -// Requires: name != NULL; -// Is the given name associated with some attributes in the current scope? -bool scope_defined(scope_t *s, const char *name) -{ - // assert(s != NULL); - // assert(name != NULL); - // debug_print("entering scope_defined for \"%s\"\n", name); - return scope_lookup(s, name) != NULL; -} - -// Requires: name != NULL and scope_initialize() has been called previously. -// Return (a pointer to) the attributes of the given name in the current scope -// or NULL if there is no association for name. -id_attrs *scope_lookup(scope_t *s, const char *name) -{ - int i; - // assert(name != NULL); - // assert(s != NULL); - // debug_print("Entering scope_lookup for \"%s\"\n", name); - for (i = 0; i < s->size; i++) { - // assert(s != NULL); - // assert(s->entries != NULL); - // assert(0 <= i && i < s->size); - // assert(s->entries[i] != NULL); - // assert(s->entries[i]->id != NULL); - // debug_print("Past asserts in scope_lookup loop\n"); - // debug_print("Length of name is %d\n", strlen(name)); - if (strcmp(s->entries[i]->id, name) == 0) { - // debug_print("scope_lookup(\"%s\") returning attributes\n", - // name); - return s->entries[i]->attrs; - } - } - // assert(i == s->size); - // debug_print("The scope_lookup call on \"%s\" returns NULL\n", name); - return NULL; -} +/* $Id: scope.c,v 1.5 2023/11/13 12:51:58 leavens Exp $ */ +#include +#include +#include +#include +#include "scope.h" +#include "utilities.h" + +// Allocate a fresh scope symbol table and return (a pointer to) it. +// Issues an error message (on stderr) if there is no space +// and exits with a failure error code in that case. +scope_t *scope_create() +{ + scope_t *new_s + = (scope_t *) malloc(sizeof(scope_t)); + if (new_s == NULL) { + bail_with_error("No space for new scope_t!"); + } + new_s->size = 0; + new_s->loc_count = 0; + for (int j = 0; j < MAX_SCOPE_SIZE; j++) { + new_s->entries[j] = NULL; + } + return new_s; +} + +// Return the number of constant and variables declarations +// that have been added to this scope. +extern unsigned int scope_loc_count(scope_t *s) +{ + return s->loc_count; +} + +// Return the current scope's size (number of declared ids). +unsigned int scope_size(scope_t *s) +{ + return s->size; +} + +// Is the current scope full? +bool scope_full(scope_t *s) +{ + return scope_size(s) >= MAX_SCOPE_SIZE; +} + +// Requires: assoc != NULL && !scope_full() && !scope_defined(assoc->id); +// Add an association from the given name to the given id attributes +// in the current scope. +// If assoc->attrs->kind != procedure_idk, +// then this stores the scope_count value into assoc->attrs->offset_count +// and then increases loc_count by 1. +static void scope_add(scope_t *s, scope_assoc_t *assoc) +{ + // assert(assoc != NULL); + // assert(!scope_full()); + // assert(!scope_defined(assoc->id)); + if (assoc->attrs->kind != procedure_idk) { + (assoc->attrs->offset_count) = (s->loc_count)++; + } + s->entries[(s->size)++] = assoc; + // fprintf(stderr, "assoc->attrs->offset_count is %d\n", + // assoc->attrs->offset_count); +} + +// Requires: !scope_defined(name) && attrs != NULL; +// Modify the current scope symbol table to +// add an association from the given name to the given id_attrs attrs, +// and if attrs->kind != procedure, +// then this stores the loc_count value into attrs->offset_count +// and then increases the loc_count for this scope by 1. +void scope_insert(scope_t *s, const char *name, id_attrs *attrs) +{ + // assert(!scope_defined(name)); + // assert(attrs != NULL); + // debug_print("Running scope_insert for name "%s\"\n", name); + scope_assoc_t *new_assoc = malloc(sizeof(scope_assoc_t)); + if (new_assoc == NULL) { + bail_with_error("No space for association!"); + } + new_assoc->id = name; + new_assoc->attrs = attrs; + scope_add(s, new_assoc); +} + +// Requires: name != NULL; +// Is the given name associated with some attributes in the current scope? +bool scope_defined(scope_t *s, const char *name) +{ + // assert(s != NULL); + // assert(name != NULL); + // debug_print("entering scope_defined for \"%s\"\n", name); + return scope_lookup(s, name) != NULL; +} + +// Requires: name != NULL and scope_initialize() has been called previously. +// Return (a pointer to) the attributes of the given name in the current scope +// or NULL if there is no association for name. +id_attrs *scope_lookup(scope_t *s, const char *name) +{ + int i; + // assert(name != NULL); + // assert(s != NULL); + // debug_print("Entering scope_lookup for \"%s\"\n", name); + for (i = 0; i < s->size; i++) { + // assert(s != NULL); + // assert(s->entries != NULL); + // assert(0 <= i && i < s->size); + // assert(s->entries[i] != NULL); + // assert(s->entries[i]->id != NULL); + // debug_print("Past asserts in scope_lookup loop\n"); + // debug_print("Length of name is %d\n", strlen(name)); + if (strcmp(s->entries[i]->id, name) == 0) { + // debug_print("scope_lookup(\"%s\") returning attributes\n", + // name); + return s->entries[i]->attrs; + } + } + // assert(i == s->size); + // debug_print("The scope_lookup call on \"%s\" returns NULL\n", name); + return NULL; +} diff --git a/scope.h b/FromGithub/scope.h old mode 100755 new mode 100644 similarity index 97% rename from scope.h rename to FromGithub/scope.h index b488344..b8d4361 --- a/scope.h +++ b/FromGithub/scope.h @@ -1,55 +1,55 @@ -/* $Id: scope.h,v 1.3 2023/11/13 12:51:59 leavens Exp $ */ -#ifndef _SCOPE_H -#define _SCOPE_H - -#include -#include "ast.h" -#include "machine_types.h" -#include "id_attrs.h" - -// Maximum number of declarations that can be stored in a scope -#define MAX_SCOPE_SIZE 4096 - -typedef struct { - const char *id; - id_attrs *attrs; -} scope_assoc_t; - -// Invariant: 0 <= size < MAX_SCOPE_SIZE; -typedef struct scope_s { - unsigned int size; - unsigned int loc_count; // number of consts and vars in this scope - scope_assoc_t *entries[MAX_SCOPE_SIZE]; -} scope_t; - -// Allocate a fresh scope symbol table and return (a pointer to) it. -// Issues an error message (on stderr) if there is no space -// and exits with a failure error code in that case. -extern scope_t *scope_create(); - -// Return the number of constant and variables declarations -// that have been added to this scope. -extern address_type scope_loc_count(scope_t *s); - -// Return the number of declared identifier associations in s -extern unsigned int scope_size(scope_t *s); - -// Is the current scope full? -extern bool scope_full(scope_t *s); - -// Is the given name associated with some attributes in the current scope? -extern bool scope_defined(scope_t *s, const char *name); - -// Requires: !scope_defined(name) && attrs != NULL; -// Modify the current scope symbol table to -// add an association from the given name to the given id_attrs attrs, -// and if attrs->id_kind != procedure, -// then this stores the next_loc_offset value into attrs->loc_offset -// and then increases the next_loc_offset for this scope by 1. -extern void scope_insert(scope_t *s, const char *name, id_attrs *attrs); - -// Return (a pointer to) the attributes of the given name in the current scope -// or NULL if there is no association for name. -extern id_attrs *scope_lookup(scope_t *s, const char *name); - -#endif +/* $Id: scope.h,v 1.3 2023/11/13 12:51:59 leavens Exp $ */ +#ifndef _SCOPE_H +#define _SCOPE_H + +#include +#include "ast.h" +#include "machine_types.h" +#include "id_attrs.h" + +// Maximum number of declarations that can be stored in a scope +#define MAX_SCOPE_SIZE 4096 + +typedef struct { + const char *id; + id_attrs *attrs; +} scope_assoc_t; + +// Invariant: 0 <= size < MAX_SCOPE_SIZE; +typedef struct scope_s { + unsigned int size; + unsigned int loc_count; // number of consts and vars in this scope + scope_assoc_t *entries[MAX_SCOPE_SIZE]; +} scope_t; + +// Allocate a fresh scope symbol table and return (a pointer to) it. +// Issues an error message (on stderr) if there is no space +// and exits with a failure error code in that case. +extern scope_t *scope_create(); + +// Return the number of constant and variables declarations +// that have been added to this scope. +extern address_type scope_loc_count(scope_t *s); + +// Return the number of declared identifier associations in s +extern unsigned int scope_size(scope_t *s); + +// Is the current scope full? +extern bool scope_full(scope_t *s); + +// Is the given name associated with some attributes in the current scope? +extern bool scope_defined(scope_t *s, const char *name); + +// Requires: !scope_defined(name) && attrs != NULL; +// Modify the current scope symbol table to +// add an association from the given name to the given id_attrs attrs, +// and if attrs->id_kind != procedure, +// then this stores the next_loc_offset value into attrs->loc_offset +// and then increases the next_loc_offset for this scope by 1. +extern void scope_insert(scope_t *s, const char *name, id_attrs *attrs); + +// Return (a pointer to) the attributes of the given name in the current scope +// or NULL if there is no association for name. +extern id_attrs *scope_lookup(scope_t *s, const char *name); + +#endif diff --git a/FromGithub/scope.o b/FromGithub/scope.o new file mode 100644 index 0000000..9d32280 Binary files /dev/null and b/FromGithub/scope.o differ diff --git a/scope_check.c b/FromGithub/scope_check.c old mode 100755 new mode 100644 similarity index 96% rename from scope_check.c rename to FromGithub/scope_check.c index fe712e7..0f21c23 --- a/scope_check.c +++ b/FromGithub/scope_check.c @@ -1,411 +1,411 @@ -/* $Id: scope_check.c,v 1.21 2024/11/13 15:23:58 leavens Exp $ */ -#include -#include -#include -#include "scope_check.h" -#include "id_attrs.h" -#include "file_location.h" -#include "ast.h" -#include "utilities.h" -#include "symtab.h" -#include "scope_check.h" - -// Requires: prog != NULL. -// The pointer passed to this function should point to the AST -// used by the compiler to generate code, so that the changes -// made (to the id_use fields) are communicated to the code generator. -// Build the symbol table for the given program AST -// and Check the given program AST for duplicate declarations -// or uses of identifiers that were not declared. -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_program(block_t *prog) -{ - scope_check_block(prog); -} - -// build the symbol table and check the declarations in blk -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_block(block_t *blk) -{ - symtab_enter_scope(); - scope_check_constDecls(blk->const_decls); - scope_check_varDecls(blk->var_decls); - scope_check_procDecls(&(blk->proc_decls)); - scope_check_stmts(&(blk->stmts)); - symtab_leave_scope(); -} - -// build the symbol table and check the declarations in cds -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_constDecls(const_decls_t cds) -{ - const_decl_t *dcl = cds.start; - while (dcl != NULL) { - scope_check_constDecl(*(dcl)); - dcl = dcl->next; - } -} - -// build the symbol table and check the const declaration cd -// and add its const-defs to the current scope's symbol table -// or produce an error if these names have already been declared -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_constDecl(const_decl_t cd) -{ - scope_check_const_def_list(cd.const_def_list); -} - -// build the symbol table and check the const definitions cdfs -// and add the declared names to the current scope's symbol table -// or produce an error if these names have already been declared -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_const_def_list(const_def_list_t cdl) -{ - const_def_t *cdf = cdl.start; - while (cdf != NULL) { - scope_check_constDef(*(cdf)); - cdf = cdf->next; - } -} - -// Put the given name, which is to be declared with kind k, -// and has its declaration at the given file location (floc), -// into the current scope's symbol table at the offset scope_size(). -// Modifies the given AST to have appropriate id_use pointers. -static void add_ident_to_scope(const char *name, id_kind k, file_location floc) -{ - id_use *idu = symtab_lookup(name); - if (idu != NULL && idu->levelsOutward == 0) { - bail_with_prog_error(floc, - "%s \"%s\" is already declared as a %s", - id_attrs_id_kind_string(k), - name, - id_attrs_id_kind_string( - id_use_get_attrs(idu)->kind)); - } else { - symtab_insert(name, - id_attrs_create(floc, k, symtab_scope_loc_count())); - } -} - -// build the symbol table and check the const definition cdf -// and add the declared name to the current scope's symbol table -// or produce an error if this name has already been declared -void scope_check_constDef(const_def_t cdf) -{ - add_ident_to_scope(cdf.ident.name, constant_idk, *(cdf.file_loc)); -} - -// build the symbol table and check the declarations in vds -void scope_check_varDecls(var_decls_t vds) -{ - var_decl_t *vdp = vds.var_decls; - while (vdp != NULL) { - scope_check_varDecl(*vdp); - vdp = vdp->next; - } -} - -// check the var declaration vd -// and add the declared names to the current scope's symbol table -// or produce an error if the names have already been declared -void scope_check_varDecl(var_decl_t vd) -{ - scope_check_varIdentList(vd.ident_list); -} - -// check the identifiers from a var declaration, as given in ids -// and add the declared names to the current scope's symbol table -// or produce an error if the names have already been declared -void scope_check_varIdentList(ident_list_t idl) -{ - ident_t *idp = idl.start; - while (idp != NULL) { - add_ident_to_scope(idp->name, variable_idk, *(idp->file_loc)); - idp = idp->next; - } -} - -// build the symbol table and check the declarations in pds -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_procDecls(proc_decls_t *pds) -{ - proc_decl_t *pdp = pds->proc_decls; - while (pdp != NULL) { - scope_check_procDecl(pdp); - pdp = pdp->next; - } -} - -// check the procedure declaration pd -// and add it to the current scope's symbol table -// or produce an error if its name has already been declared -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_procDecl(proc_decl_t *pd) -{ - // add name to scope first, so that the procedure can be recursive - add_ident_to_scope(pd->name, procedure_idk, *(pd->file_loc)); - scope_check_block(pd->block); -} - -// check all the statement in stmts to make sure that -// all idenfifiers referenced in them have been declared -// (if not, then produce an error) -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_stmts(stmts_t *stmts) -{ - if (stmts->stmts_kind != empty_stmts_e) { - scope_check_stmtList(&(stmts->stmt_list)); - } -} - -// check all the statement in stmt_list to make sure that -// all idenfifiers referenced in them have been declared -// (if not, then produce an error) -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_stmtList(stmt_list_t *stmt_list) -{ - stmt_t *s = stmt_list->start; - while (s != NULL) { - scope_check_stmt(s); - s = s->next; - } -} - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_stmt(stmt_t *stmt) -{ - switch (stmt->stmt_kind) { - case assign_stmt: - scope_check_assignStmt(&(stmt->data.assign_stmt)); - break; - case call_stmt: - scope_check_callStmt(&(stmt->data.call_stmt)); - break; - case if_stmt: - scope_check_ifStmt(&(stmt->data.if_stmt)); - break; - case while_stmt: - scope_check_whileStmt(&(stmt->data.while_stmt)); - break; - case read_stmt: - scope_check_readStmt(&(stmt->data.read_stmt)); - break; - case print_stmt: - scope_check_printStmt(&(stmt->data.print_stmt)); - print_stmt_t ps = stmt->data.print_stmt; - if (ps.expr.expr_kind == expr_ident) { - assert(ps.expr.data.ident.idu != NULL); - } - break; - case block_stmt: - scope_check_blockStmt(&(stmt->data.block_stmt)); - break; - default: - bail_with_error("Unknown stmt_kind (%d) in scope_check_stmt!", - stmt->stmt_kind); - break; - } -} - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_assignStmt(assign_stmt_t *stmt) -{ - stmt->idu = scope_check_ident_declared(*(stmt->file_loc), stmt->name); - id_attrs attrs = *(stmt->idu->attrs); - if (attrs.kind != variable_idk) { - bail_with_prog_error(attrs.file_loc, - "Must be a variable on the left-hand side of an assignment statement, not the %s \"%s\"", - id_attrs_id_kind_string(attrs.kind), - stmt->name); - } - scope_check_expr(stmt->expr); -} - -// check the statement to make sure that -// the procedure being called has been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_callStmt(call_stmt_t *stmt) -{ - stmt->idu = scope_check_ident_declared(*(stmt->file_loc), stmt->name); -} - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_blockStmt(block_stmt_t *stmt) -{ - scope_check_block(stmt->block); -} - - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_ifStmt(if_stmt_t *stmt) -{ - scope_check_condition(&(stmt->condition)); - scope_check_stmts(stmt->then_stmts); - if (stmt->else_stmts != NULL) { - scope_check_stmts(stmt->else_stmts); - } -} - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_whileStmt(while_stmt_t *stmt) -{ - scope_check_condition(&(stmt->condition)); - scope_check_stmts(stmt->body); -} - -// Check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_readStmt(read_stmt_t *stmt) -{ - stmt->idu = scope_check_ident_declared(*(stmt->file_loc), stmt->name); - id_attrs attrs = *(stmt->idu->attrs); - if (attrs.kind != variable_idk) { - bail_with_prog_error(attrs.file_loc, - "The name (%s) in a read statement must be a variable, not a %s", - stmt->name, - id_attrs_id_kind_string(attrs.kind)); - } -} - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_printStmt(print_stmt_t *stmt) -{ - scope_check_expr(&(stmt->expr)); - if (stmt->expr.expr_kind == expr_ident) { - assert(stmt->expr.data.ident.idu != NULL); - } -} - -// check the condition to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_condition(condition_t *cond) -{ - switch (cond->cond_kind){ - case ck_db: - scope_check_db_condition(&(cond->data.db_cond)); - break; - case ck_rel: - scope_check_rel_op_condition(&(cond->data.rel_op_cond)); - break; - default: - bail_with_error("Unexpected type_tag (%d) in scope_check_cond!", - cond->cond_kind); - break; - } -} - -// check the condition to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_db_condition(db_condition_t *cond) -{ - scope_check_expr(&(cond->dividend)); - scope_check_expr(&(cond->divisor)); -} - -// check the condition to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_rel_op_condition(rel_op_condition_t *cond) -{ - scope_check_expr(&(cond->expr1)); - scope_check_expr(&(cond->expr2)); -} - -// check the expresion to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_expr(expr_t *exp) -{ - switch (exp->expr_kind) { - case expr_ident: - scope_check_ident(&(exp->data.ident)); - assert(exp->data.ident.idu != NULL); - break; - case expr_negated: - scope_check_expr(exp->data.negated.expr); - break; - case expr_bin: - scope_check_binary_op_expr(&(exp->data.binary)); - break; - case expr_number: - // no identifiers are possible in this case, so just return - break; - default: - bail_with_error("Unexpected expr_kind_e (%d) in scope_check_expr!", - exp->expr_kind); - break; - } -} - -// check that the given name has been declared, -// if not, then produce an error using the file_location (floc) given. -// Modifies the given AST to have appropriate id_use pointers. -void scope_check_ident(ident_t *id) -{ - file_location floc = *(id->file_loc); - const char *name = id->name; - id_use *idu = scope_check_ident_declared(floc, name); - if (idu == NULL) { - bail_with_prog_error(floc, - "identifier \"%s\" has not been declared!", - name); - } - id->idu = idu; -} - -// check the expression (exp) to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error) -void scope_check_binary_op_expr(binary_op_expr_t *exp) -{ - scope_check_expr(exp->expr1); - scope_check_expr(exp->expr2); -} - -// Check that the given name has been declared, -// if so, then return an id_use -// (containing the attributes) for that name, -// otherwise, produce an error -// using the file_location (floc) given. -id_use *scope_check_ident_declared( - file_location floc, - const char *name) -{ - id_use *ret = symtab_lookup(name); - if (ret == NULL) { - bail_with_prog_error(floc, - "identifier \"%s\" is not declared!", - name); - } - id_attrs *ret_attrs = id_use_get_attrs(ret); - assert(ret_attrs != NULL); - return ret; -} +/* $Id: scope_check.c,v 1.21 2024/11/13 15:23:58 leavens Exp $ */ +#include +#include +#include +#include "scope_check.h" +#include "id_attrs.h" +#include "file_location.h" +#include "ast.h" +#include "utilities.h" +#include "symtab.h" +#include "scope_check.h" + +// Requires: prog != NULL. +// The pointer passed to this function should point to the AST +// used by the compiler to generate code, so that the changes +// made (to the id_use fields) are communicated to the code generator. +// Build the symbol table for the given program AST +// and Check the given program AST for duplicate declarations +// or uses of identifiers that were not declared. +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_program(block_t *prog) +{ + scope_check_block(prog); +} + +// build the symbol table and check the declarations in blk +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_block(block_t *blk) +{ + symtab_enter_scope(); + scope_check_constDecls(blk->const_decls); + scope_check_varDecls(blk->var_decls); + scope_check_procDecls(&(blk->proc_decls)); + scope_check_stmts(&(blk->stmts)); + symtab_leave_scope(); +} + +// build the symbol table and check the declarations in cds +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_constDecls(const_decls_t cds) +{ + const_decl_t *dcl = cds.start; + while (dcl != NULL) { + scope_check_constDecl(*(dcl)); + dcl = dcl->next; + } +} + +// build the symbol table and check the const declaration cd +// and add its const-defs to the current scope's symbol table +// or produce an error if these names have already been declared +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_constDecl(const_decl_t cd) +{ + scope_check_const_def_list(cd.const_def_list); +} + +// build the symbol table and check the const definitions cdfs +// and add the declared names to the current scope's symbol table +// or produce an error if these names have already been declared +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_const_def_list(const_def_list_t cdl) +{ + const_def_t *cdf = cdl.start; + while (cdf != NULL) { + scope_check_constDef(*(cdf)); + cdf = cdf->next; + } +} + +// Put the given name, which is to be declared with kind k, +// and has its declaration at the given file location (floc), +// into the current scope's symbol table at the offset scope_size(). +// Modifies the given AST to have appropriate id_use pointers. +static void add_ident_to_scope(const char *name, id_kind k, file_location floc) +{ + id_use *idu = symtab_lookup(name); + if (idu != NULL && idu->levelsOutward == 0) { + bail_with_prog_error(floc, + "%s \"%s\" is already declared as a %s", + id_attrs_id_kind_string(k), + name, + id_attrs_id_kind_string( + id_use_get_attrs(idu)->kind)); + } else { + symtab_insert(name, + id_attrs_create(floc, k, symtab_scope_loc_count())); + } +} + +// build the symbol table and check the const definition cdf +// and add the declared name to the current scope's symbol table +// or produce an error if this name has already been declared +void scope_check_constDef(const_def_t cdf) +{ + add_ident_to_scope(cdf.ident.name, constant_idk, *(cdf.file_loc)); +} + +// build the symbol table and check the declarations in vds +void scope_check_varDecls(var_decls_t vds) +{ + var_decl_t *vdp = vds.var_decls; + while (vdp != NULL) { + scope_check_varDecl(*vdp); + vdp = vdp->next; + } +} + +// check the var declaration vd +// and add the declared names to the current scope's symbol table +// or produce an error if the names have already been declared +void scope_check_varDecl(var_decl_t vd) +{ + scope_check_varIdentList(vd.ident_list); +} + +// check the identifiers from a var declaration, as given in ids +// and add the declared names to the current scope's symbol table +// or produce an error if the names have already been declared +void scope_check_varIdentList(ident_list_t idl) +{ + ident_t *idp = idl.start; + while (idp != NULL) { + add_ident_to_scope(idp->name, variable_idk, *(idp->file_loc)); + idp = idp->next; + } +} + +// build the symbol table and check the declarations in pds +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_procDecls(proc_decls_t *pds) +{ + proc_decl_t *pdp = pds->proc_decls; + while (pdp != NULL) { + scope_check_procDecl(pdp); + pdp = pdp->next; + } +} + +// check the procedure declaration pd +// and add it to the current scope's symbol table +// or produce an error if its name has already been declared +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_procDecl(proc_decl_t *pd) +{ + // add name to scope first, so that the procedure can be recursive + add_ident_to_scope(pd->name, procedure_idk, *(pd->file_loc)); + scope_check_block(pd->block); +} + +// check all the statement in stmts to make sure that +// all idenfifiers referenced in them have been declared +// (if not, then produce an error) +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_stmts(stmts_t *stmts) +{ + if (stmts->stmts_kind != empty_stmts_e) { + scope_check_stmtList(&(stmts->stmt_list)); + } +} + +// check all the statement in stmt_list to make sure that +// all idenfifiers referenced in them have been declared +// (if not, then produce an error) +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_stmtList(stmt_list_t *stmt_list) +{ + stmt_t *s = stmt_list->start; + while (s != NULL) { + scope_check_stmt(s); + s = s->next; + } +} + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_stmt(stmt_t *stmt) +{ + switch (stmt->stmt_kind) { + case assign_stmt: + scope_check_assignStmt(&(stmt->data.assign_stmt)); + break; + case call_stmt: + scope_check_callStmt(&(stmt->data.call_stmt)); + break; + case if_stmt: + scope_check_ifStmt(&(stmt->data.if_stmt)); + break; + case while_stmt: + scope_check_whileStmt(&(stmt->data.while_stmt)); + break; + case read_stmt: + scope_check_readStmt(&(stmt->data.read_stmt)); + break; + case print_stmt: + scope_check_printStmt(&(stmt->data.print_stmt)); + print_stmt_t ps = stmt->data.print_stmt; + if (ps.expr.expr_kind == expr_ident) { + assert(ps.expr.data.ident.idu != NULL); + } + break; + case block_stmt: + scope_check_blockStmt(&(stmt->data.block_stmt)); + break; + default: + bail_with_error("Unknown stmt_kind (%d) in scope_check_stmt!", + stmt->stmt_kind); + break; + } +} + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_assignStmt(assign_stmt_t *stmt) +{ + stmt->idu = scope_check_ident_declared(*(stmt->file_loc), stmt->name); + id_attrs attrs = *(stmt->idu->attrs); + if (attrs.kind != variable_idk) { + bail_with_prog_error(attrs.file_loc, + "Must be a variable on the left-hand side of an assignment statement, not the %s \"%s\"", + id_attrs_id_kind_string(attrs.kind), + stmt->name); + } + scope_check_expr(stmt->expr); +} + +// check the statement to make sure that +// the procedure being called has been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_callStmt(call_stmt_t *stmt) +{ + stmt->idu = scope_check_ident_declared(*(stmt->file_loc), stmt->name); +} + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_blockStmt(block_stmt_t *stmt) +{ + scope_check_block(stmt->block); +} + + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_ifStmt(if_stmt_t *stmt) +{ + scope_check_condition(&(stmt->condition)); + scope_check_stmts(stmt->then_stmts); + if (stmt->else_stmts != NULL) { + scope_check_stmts(stmt->else_stmts); + } +} + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_whileStmt(while_stmt_t *stmt) +{ + scope_check_condition(&(stmt->condition)); + scope_check_stmts(stmt->body); +} + +// Check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_readStmt(read_stmt_t *stmt) +{ + stmt->idu = scope_check_ident_declared(*(stmt->file_loc), stmt->name); + id_attrs attrs = *(stmt->idu->attrs); + if (attrs.kind != variable_idk) { + bail_with_prog_error(attrs.file_loc, + "The name (%s) in a read statement must be a variable, not a %s", + stmt->name, + id_attrs_id_kind_string(attrs.kind)); + } +} + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_printStmt(print_stmt_t *stmt) +{ + scope_check_expr(&(stmt->expr)); + if (stmt->expr.expr_kind == expr_ident) { + assert(stmt->expr.data.ident.idu != NULL); + } +} + +// check the condition to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_condition(condition_t *cond) +{ + switch (cond->cond_kind){ + case ck_db: + scope_check_db_condition(&(cond->data.db_cond)); + break; + case ck_rel: + scope_check_rel_op_condition(&(cond->data.rel_op_cond)); + break; + default: + bail_with_error("Unexpected type_tag (%d) in scope_check_cond!", + cond->cond_kind); + break; + } +} + +// check the condition to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_db_condition(db_condition_t *cond) +{ + scope_check_expr(&(cond->dividend)); + scope_check_expr(&(cond->divisor)); +} + +// check the condition to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_rel_op_condition(rel_op_condition_t *cond) +{ + scope_check_expr(&(cond->expr1)); + scope_check_expr(&(cond->expr2)); +} + +// check the expresion to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_expr(expr_t *exp) +{ + switch (exp->expr_kind) { + case expr_ident: + scope_check_ident(&(exp->data.ident)); + assert(exp->data.ident.idu != NULL); + break; + case expr_negated: + scope_check_expr(exp->data.negated.expr); + break; + case expr_bin: + scope_check_binary_op_expr(&(exp->data.binary)); + break; + case expr_number: + // no identifiers are possible in this case, so just return + break; + default: + bail_with_error("Unexpected expr_kind_e (%d) in scope_check_expr!", + exp->expr_kind); + break; + } +} + +// check that the given name has been declared, +// if not, then produce an error using the file_location (floc) given. +// Modifies the given AST to have appropriate id_use pointers. +void scope_check_ident(ident_t *id) +{ + file_location floc = *(id->file_loc); + const char *name = id->name; + id_use *idu = scope_check_ident_declared(floc, name); + if (idu == NULL) { + bail_with_prog_error(floc, + "identifier \"%s\" has not been declared!", + name); + } + id->idu = idu; +} + +// check the expression (exp) to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error) +void scope_check_binary_op_expr(binary_op_expr_t *exp) +{ + scope_check_expr(exp->expr1); + scope_check_expr(exp->expr2); +} + +// Check that the given name has been declared, +// if so, then return an id_use +// (containing the attributes) for that name, +// otherwise, produce an error +// using the file_location (floc) given. +id_use *scope_check_ident_declared( + file_location floc, + const char *name) +{ + id_use *ret = symtab_lookup(name); + if (ret == NULL) { + bail_with_prog_error(floc, + "identifier \"%s\" is not declared!", + name); + } + id_attrs *ret_attrs = id_use_get_attrs(ret); + assert(ret_attrs != NULL); + return ret; +} diff --git a/scope_check.h b/FromGithub/scope_check.h old mode 100755 new mode 100644 similarity index 97% rename from scope_check.h rename to FromGithub/scope_check.h index cf678dd..1d72b76 --- a/scope_check.h +++ b/FromGithub/scope_check.h @@ -1,166 +1,166 @@ -/* $Id: scope_check.h,v 1.9 2024/11/10 12:54:14 leavens Exp $ */ -#ifndef _SCOPE_CHECK_H -#define _SCOPE_CHECK_H -#include "ast.h" - -// Requires: prog != NULL. -// The pointer passed to this function should point to the AST -// used by the compiler to generate code, so that the changes -// made (to the id_use fields) are communicated to the code generator. -// Build the symbol table for the given program AST -// and Check the given program AST for duplicate declarations -// or uses of identifiers that were not declared. -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_program(block_t *prog); - -// build the symbol table and check the declarations in blk -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_block(block_t *blk); - -// build the symbol table and check the declarations in cds -extern void scope_check_constDecls(const_decls_t cds); - -// build the symbol table and check the const declaration cd -// and add its const-defs to the current scope's symbol table -// or produce an error if these names have already been declared -extern void scope_check_constDecl(const_decl_t cd); - -// build the symbol table and check the const definitions cdfs -// and add the declared names to the current scope's symbol table -// or produce an error if these names have already been declared -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_const_def_list(const_def_list_t cdl); - -// build the symbol table and check the const definition cdf -// and add the declared name to the current scope's symbol table -// or produce an error if its name has already been declared -extern void scope_check_constDef(const_def_t cdf); - -// build the symbol table and check the declarations in vds -extern void scope_check_varDecls(var_decls_t vds); - -// check the var declaration vd -// and add the declared names to the current scope's symbol table -// or produce an error if the names have already been declared -extern void scope_check_varDecl(var_decl_t vd); - -// check the identifiers from a var declaration, as given in ids -// and add the declared names to the current scope's symbol table -// or produce an error if the names have already been declared -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_varIdentList(ident_list_t ident_list); - -// build the symbol table and check the declarations in pds -extern void scope_check_procDecls(proc_decls_t *pds); - -// check the procedure declaration pd -// and add it to the current scope's symbol table -// or produce an error if its name has already been declared -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_procDecl(proc_decl_t *pd); - -// check all the statement in stmts to make sure that -// all idenfifiers referenced in them have been declared -// (if not, then produce an error) -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_stmts(stmts_t *stmts); - -// check all the statement in stmt_list to make sure that -// all idenfifiers referenced in them have been declared -// (if not, then produce an error) -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_stmtList(stmt_list_t *stmt_list); - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_stmt(stmt_t *stmt); - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_assignStmt(assign_stmt_t *stmt); - -// check the statement to make sure that -// the procedure being called has been declared -// (if not, then produce an error) -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_callStmt(call_stmt_t *stmt); - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error) -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_blockStmt(block_stmt_t *block); - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error) -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_ifStmt(if_stmt_t *stmt); - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error) -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_whileStmt(while_stmt_t *stmt); - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error) -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_readStmt(read_stmt_t *stmt); - -// check the statement to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_printStmt(print_stmt_t *stmt); - -// check the condition to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_condition(condition_t *cond); - -// check the condition to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_db_condition(db_condition_t *cond); - -// check the condition to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_rel_op_condition(rel_op_condition_t *cond); - -// check the expresion to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error). -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_expr(expr_t *exp); - -// check that the given name has been declared, -// if not, then produce an error using the file_location (floc) given. -// Modifies the AST to have appropriate id_use pointers. -extern void scope_check_ident(ident_t *id); - -// check the expression (exp) to make sure that -// all idenfifiers referenced in it have been declared -// (if not, then produce an error) -// Modifies the given AST to have appropriate id_use pointers. -extern void scope_check_binary_op_expr(binary_op_expr_t *exp); - -// Check that the given name has been declared, -// if so, then return an id_use -// (containing the attributes) for that name, -// otherwise, produce an error -// using the file_location (floc) given. -extern id_use *scope_check_ident_declared( - file_location floc, - const char *name); - -#endif +/* $Id: scope_check.h,v 1.9 2024/11/10 12:54:14 leavens Exp $ */ +#ifndef _SCOPE_CHECK_H +#define _SCOPE_CHECK_H +#include "ast.h" + +// Requires: prog != NULL. +// The pointer passed to this function should point to the AST +// used by the compiler to generate code, so that the changes +// made (to the id_use fields) are communicated to the code generator. +// Build the symbol table for the given program AST +// and Check the given program AST for duplicate declarations +// or uses of identifiers that were not declared. +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_program(block_t *prog); + +// build the symbol table and check the declarations in blk +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_block(block_t *blk); + +// build the symbol table and check the declarations in cds +extern void scope_check_constDecls(const_decls_t cds); + +// build the symbol table and check the const declaration cd +// and add its const-defs to the current scope's symbol table +// or produce an error if these names have already been declared +extern void scope_check_constDecl(const_decl_t cd); + +// build the symbol table and check the const definitions cdfs +// and add the declared names to the current scope's symbol table +// or produce an error if these names have already been declared +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_const_def_list(const_def_list_t cdl); + +// build the symbol table and check the const definition cdf +// and add the declared name to the current scope's symbol table +// or produce an error if its name has already been declared +extern void scope_check_constDef(const_def_t cdf); + +// build the symbol table and check the declarations in vds +extern void scope_check_varDecls(var_decls_t vds); + +// check the var declaration vd +// and add the declared names to the current scope's symbol table +// or produce an error if the names have already been declared +extern void scope_check_varDecl(var_decl_t vd); + +// check the identifiers from a var declaration, as given in ids +// and add the declared names to the current scope's symbol table +// or produce an error if the names have already been declared +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_varIdentList(ident_list_t ident_list); + +// build the symbol table and check the declarations in pds +extern void scope_check_procDecls(proc_decls_t *pds); + +// check the procedure declaration pd +// and add it to the current scope's symbol table +// or produce an error if its name has already been declared +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_procDecl(proc_decl_t *pd); + +// check all the statement in stmts to make sure that +// all idenfifiers referenced in them have been declared +// (if not, then produce an error) +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_stmts(stmts_t *stmts); + +// check all the statement in stmt_list to make sure that +// all idenfifiers referenced in them have been declared +// (if not, then produce an error) +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_stmtList(stmt_list_t *stmt_list); + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_stmt(stmt_t *stmt); + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_assignStmt(assign_stmt_t *stmt); + +// check the statement to make sure that +// the procedure being called has been declared +// (if not, then produce an error) +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_callStmt(call_stmt_t *stmt); + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error) +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_blockStmt(block_stmt_t *block); + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error) +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_ifStmt(if_stmt_t *stmt); + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error) +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_whileStmt(while_stmt_t *stmt); + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error) +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_readStmt(read_stmt_t *stmt); + +// check the statement to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_printStmt(print_stmt_t *stmt); + +// check the condition to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_condition(condition_t *cond); + +// check the condition to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_db_condition(db_condition_t *cond); + +// check the condition to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_rel_op_condition(rel_op_condition_t *cond); + +// check the expresion to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error). +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_expr(expr_t *exp); + +// check that the given name has been declared, +// if not, then produce an error using the file_location (floc) given. +// Modifies the AST to have appropriate id_use pointers. +extern void scope_check_ident(ident_t *id); + +// check the expression (exp) to make sure that +// all idenfifiers referenced in it have been declared +// (if not, then produce an error) +// Modifies the given AST to have appropriate id_use pointers. +extern void scope_check_binary_op_expr(binary_op_expr_t *exp); + +// Check that the given name has been declared, +// if so, then return an id_use +// (containing the attributes) for that name, +// otherwise, produce an error +// using the file_location (floc) given. +extern id_use *scope_check_ident_declared( + file_location floc, + const char *name); + +#endif diff --git a/FromGithub/scope_check.o b/FromGithub/scope_check.o new file mode 100644 index 0000000..c21dff3 Binary files /dev/null and b/FromGithub/scope_check.o differ diff --git a/FromGithub/spl.output b/FromGithub/spl.output new file mode 100644 index 0000000..6802708 --- /dev/null +++ b/FromGithub/spl.output @@ -0,0 +1,1265 @@ +Grammar + + 0 $accept: program $end + + 1 program: block "." + + 2 block: "begin" constDecls varDecls procDecls stmts "end" + + 3 constDecls: empty + 4 | constDecls constDecl + + 5 empty: ε + + 6 constDecl: "const" constDefList ";" + + 7 constDefList: constDef + 8 | constDefList "," constDef + + 9 constDef: identsym "=" numbersym + + 10 varDecls: empty + 11 | varDecls varDecl + + 12 varDecl: "var" identList ";" + + 13 identList: identsym + 14 | identList "," identsym + + 15 procDecls: empty + 16 | procDecls procDecl + + 17 procDecl: "proc" identsym block ";" + + 18 stmts: empty + 19 | stmtList + + 20 stmtList: stmt + 21 | stmtList ";" stmt + + 22 stmt: assignStmt + 23 | callStmt + 24 | ifStmt + 25 | whileStmt + 26 | readStmt + 27 | printStmt + 28 | blockStmt + + 29 assignStmt: identsym ":=" expr + + 30 callStmt: "call" identsym + + 31 ifStmt: "if" condition "then" stmts "else" stmts "end" + 32 | "if" condition "then" stmts "end" + + 33 whileStmt: "while" condition "do" stmts "end" + + 34 readStmt: "read" identsym + + 35 printStmt: "print" expr + + 36 blockStmt: block + + 37 condition: dbCondition + 38 | relOpCondition + + 39 dbCondition: "divisible" expr "by" expr + + 40 relOpCondition: expr relOp expr + + 41 relOp: "==" + 42 | "!=" + 43 | "<" + 44 | "<=" + 45 | ">" + 46 | ">=" + + 47 expr: term + 48 | expr "+" term + 49 | expr "-" term + + 50 term: factor + 51 | term "*" factor + 52 | term "/" factor + + 53 factor: identsym + 54 | numbersym + 55 | "-" factor + 56 | "+" factor + 57 | "(" expr ")" + + +Terminals, with rules where they appear + + $end (0) 0 + error (256) + identsym (258) 9 13 14 17 29 30 34 53 + numbersym (259) 9 54 + "+" (260) 48 56 + "-" (261) 49 55 + "*" (262) 51 + "/" (263) 52 + "." (264) 1 + ";" (265) 6 12 17 21 + "=" (266) 9 + "," (267) 8 14 + ":=" (268) 29 + "(" (269) 57 + ")" (270) 57 + "const" (271) 6 + "var" (272) 12 + "proc" (273) 17 + "call" (274) 30 + "begin" (275) 2 + "end" (276) 2 31 32 33 + "if" (277) 31 32 + "then" (278) 31 32 + "else" (279) 31 + "while" (280) 33 + "do" (281) 33 + "read" (282) 34 + "print" (283) 35 + "divisible" (284) 39 + "by" (285) 39 + "==" (286) 41 + "!=" (287) 42 + "<" (288) 43 + "<=" (289) 44 + ">" (290) 45 + ">=" (291) 46 + + +Nonterminals, with rules where they appear + + $accept (37) + on left: 0 + program (38) + on left: 1 + on right: 0 + block (39) + on left: 2 + on right: 1 17 36 + constDecls (40) + on left: 3 4 + on right: 2 4 + empty (41) + on left: 5 + on right: 3 10 15 18 + constDecl (42) + on left: 6 + on right: 4 + constDefList (43) + on left: 7 8 + on right: 6 8 + constDef (44) + on left: 9 + on right: 7 8 + varDecls (45) + on left: 10 11 + on right: 2 11 + varDecl (46) + on left: 12 + on right: 11 + identList (47) + on left: 13 14 + on right: 12 14 + procDecls (48) + on left: 15 16 + on right: 2 16 + procDecl (49) + on left: 17 + on right: 16 + stmts (50) + on left: 18 19 + on right: 2 31 32 33 + stmtList (51) + on left: 20 21 + on right: 19 21 + stmt (52) + on left: 22 23 24 25 26 27 28 + on right: 20 21 + assignStmt (53) + on left: 29 + on right: 22 + callStmt (54) + on left: 30 + on right: 23 + ifStmt (55) + on left: 31 32 + on right: 24 + whileStmt (56) + on left: 33 + on right: 25 + readStmt (57) + on left: 34 + on right: 26 + printStmt (58) + on left: 35 + on right: 27 + blockStmt (59) + on left: 36 + on right: 28 + condition (60) + on left: 37 38 + on right: 31 32 33 + dbCondition (61) + on left: 39 + on right: 37 + relOpCondition (62) + on left: 40 + on right: 38 + relOp (63) + on left: 41 42 43 44 45 46 + on right: 40 + expr (64) + on left: 47 48 49 + on right: 29 35 39 40 48 49 57 + term (65) + on left: 50 51 52 + on right: 47 48 49 51 52 + factor (66) + on left: 53 54 55 56 57 + on right: 50 51 52 55 56 + + +State 0 + + 0 $accept: • program $end + + "begin" shift, and go to state 1 + + program go to state 2 + block go to state 3 + + +State 1 + + 2 block: "begin" • constDecls varDecls procDecls stmts "end" + + $default reduce using rule 5 (empty) + + constDecls go to state 4 + empty go to state 5 + + +State 2 + + 0 $accept: program • $end + + $end shift, and go to state 6 + + +State 3 + + 1 program: block • "." + + "." shift, and go to state 7 + + +State 4 + + 2 block: "begin" constDecls • varDecls procDecls stmts "end" + 4 constDecls: constDecls • constDecl + + "const" shift, and go to state 8 + + $default reduce using rule 5 (empty) + + empty go to state 9 + constDecl go to state 10 + varDecls go to state 11 + + +State 5 + + 3 constDecls: empty • + + $default reduce using rule 3 (constDecls) + + +State 6 + + 0 $accept: program $end • + + $default accept + + +State 7 + + 1 program: block "." • + + $default reduce using rule 1 (program) + + +State 8 + + 6 constDecl: "const" • constDefList ";" + + identsym shift, and go to state 12 + + constDefList go to state 13 + constDef go to state 14 + + +State 9 + + 10 varDecls: empty • + + $default reduce using rule 10 (varDecls) + + +State 10 + + 4 constDecls: constDecls constDecl • + + $default reduce using rule 4 (constDecls) + + +State 11 + + 2 block: "begin" constDecls varDecls • procDecls stmts "end" + 11 varDecls: varDecls • varDecl + + "var" shift, and go to state 15 + + $default reduce using rule 5 (empty) + + empty go to state 16 + varDecl go to state 17 + procDecls go to state 18 + + +State 12 + + 9 constDef: identsym • "=" numbersym + + "=" shift, and go to state 19 + + +State 13 + + 6 constDecl: "const" constDefList • ";" + 8 constDefList: constDefList • "," constDef + + ";" shift, and go to state 20 + "," shift, and go to state 21 + + +State 14 + + 7 constDefList: constDef • + + $default reduce using rule 7 (constDefList) + + +State 15 + + 12 varDecl: "var" • identList ";" + + identsym shift, and go to state 22 + + identList go to state 23 + + +State 16 + + 15 procDecls: empty • + + $default reduce using rule 15 (procDecls) + + +State 17 + + 11 varDecls: varDecls varDecl • + + $default reduce using rule 11 (varDecls) + + +State 18 + + 2 block: "begin" constDecls varDecls procDecls • stmts "end" + 16 procDecls: procDecls • procDecl + + identsym shift, and go to state 24 + "proc" shift, and go to state 25 + "call" shift, and go to state 26 + "begin" shift, and go to state 1 + "if" shift, and go to state 27 + "while" shift, and go to state 28 + "read" shift, and go to state 29 + "print" shift, and go to state 30 + + $default reduce using rule 5 (empty) + + block go to state 31 + empty go to state 32 + procDecl go to state 33 + stmts go to state 34 + stmtList go to state 35 + stmt go to state 36 + assignStmt go to state 37 + callStmt go to state 38 + ifStmt go to state 39 + whileStmt go to state 40 + readStmt go to state 41 + printStmt go to state 42 + blockStmt go to state 43 + + +State 19 + + 9 constDef: identsym "=" • numbersym + + numbersym shift, and go to state 44 + + +State 20 + + 6 constDecl: "const" constDefList ";" • + + $default reduce using rule 6 (constDecl) + + +State 21 + + 8 constDefList: constDefList "," • constDef + + identsym shift, and go to state 12 + + constDef go to state 45 + + +State 22 + + 13 identList: identsym • + + $default reduce using rule 13 (identList) + + +State 23 + + 12 varDecl: "var" identList • ";" + 14 identList: identList • "," identsym + + ";" shift, and go to state 46 + "," shift, and go to state 47 + + +State 24 + + 29 assignStmt: identsym • ":=" expr + + ":=" shift, and go to state 48 + + +State 25 + + 17 procDecl: "proc" • identsym block ";" + + identsym shift, and go to state 49 + + +State 26 + + 30 callStmt: "call" • identsym + + identsym shift, and go to state 50 + + +State 27 + + 31 ifStmt: "if" • condition "then" stmts "else" stmts "end" + 32 | "if" • condition "then" stmts "end" + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + "divisible" shift, and go to state 56 + + condition go to state 57 + dbCondition go to state 58 + relOpCondition go to state 59 + expr go to state 60 + term go to state 61 + factor go to state 62 + + +State 28 + + 33 whileStmt: "while" • condition "do" stmts "end" + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + "divisible" shift, and go to state 56 + + condition go to state 63 + dbCondition go to state 58 + relOpCondition go to state 59 + expr go to state 60 + term go to state 61 + factor go to state 62 + + +State 29 + + 34 readStmt: "read" • identsym + + identsym shift, and go to state 64 + + +State 30 + + 35 printStmt: "print" • expr + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + expr go to state 65 + term go to state 61 + factor go to state 62 + + +State 31 + + 36 blockStmt: block • + + $default reduce using rule 36 (blockStmt) + + +State 32 + + 18 stmts: empty • + + $default reduce using rule 18 (stmts) + + +State 33 + + 16 procDecls: procDecls procDecl • + + $default reduce using rule 16 (procDecls) + + +State 34 + + 2 block: "begin" constDecls varDecls procDecls stmts • "end" + + "end" shift, and go to state 66 + + +State 35 + + 19 stmts: stmtList • + 21 stmtList: stmtList • ";" stmt + + ";" shift, and go to state 67 + + $default reduce using rule 19 (stmts) + + +State 36 + + 20 stmtList: stmt • + + $default reduce using rule 20 (stmtList) + + +State 37 + + 22 stmt: assignStmt • + + $default reduce using rule 22 (stmt) + + +State 38 + + 23 stmt: callStmt • + + $default reduce using rule 23 (stmt) + + +State 39 + + 24 stmt: ifStmt • + + $default reduce using rule 24 (stmt) + + +State 40 + + 25 stmt: whileStmt • + + $default reduce using rule 25 (stmt) + + +State 41 + + 26 stmt: readStmt • + + $default reduce using rule 26 (stmt) + + +State 42 + + 27 stmt: printStmt • + + $default reduce using rule 27 (stmt) + + +State 43 + + 28 stmt: blockStmt • + + $default reduce using rule 28 (stmt) + + +State 44 + + 9 constDef: identsym "=" numbersym • + + $default reduce using rule 9 (constDef) + + +State 45 + + 8 constDefList: constDefList "," constDef • + + $default reduce using rule 8 (constDefList) + + +State 46 + + 12 varDecl: "var" identList ";" • + + $default reduce using rule 12 (varDecl) + + +State 47 + + 14 identList: identList "," • identsym + + identsym shift, and go to state 68 + + +State 48 + + 29 assignStmt: identsym ":=" • expr + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + expr go to state 69 + term go to state 61 + factor go to state 62 + + +State 49 + + 17 procDecl: "proc" identsym • block ";" + + "begin" shift, and go to state 1 + + block go to state 70 + + +State 50 + + 30 callStmt: "call" identsym • + + $default reduce using rule 30 (callStmt) + + +State 51 + + 53 factor: identsym • + + $default reduce using rule 53 (factor) + + +State 52 + + 54 factor: numbersym • + + $default reduce using rule 54 (factor) + + +State 53 + + 56 factor: "+" • factor + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + factor go to state 71 + + +State 54 + + 55 factor: "-" • factor + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + factor go to state 72 + + +State 55 + + 57 factor: "(" • expr ")" + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + expr go to state 73 + term go to state 61 + factor go to state 62 + + +State 56 + + 39 dbCondition: "divisible" • expr "by" expr + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + expr go to state 74 + term go to state 61 + factor go to state 62 + + +State 57 + + 31 ifStmt: "if" condition • "then" stmts "else" stmts "end" + 32 | "if" condition • "then" stmts "end" + + "then" shift, and go to state 75 + + +State 58 + + 37 condition: dbCondition • + + $default reduce using rule 37 (condition) + + +State 59 + + 38 condition: relOpCondition • + + $default reduce using rule 38 (condition) + + +State 60 + + 40 relOpCondition: expr • relOp expr + 48 expr: expr • "+" term + 49 | expr • "-" term + + "+" shift, and go to state 76 + "-" shift, and go to state 77 + "==" shift, and go to state 78 + "!=" shift, and go to state 79 + "<" shift, and go to state 80 + "<=" shift, and go to state 81 + ">" shift, and go to state 82 + ">=" shift, and go to state 83 + + relOp go to state 84 + + +State 61 + + 47 expr: term • + 51 term: term • "*" factor + 52 | term • "/" factor + + "*" shift, and go to state 85 + "/" shift, and go to state 86 + + $default reduce using rule 47 (expr) + + +State 62 + + 50 term: factor • + + $default reduce using rule 50 (term) + + +State 63 + + 33 whileStmt: "while" condition • "do" stmts "end" + + "do" shift, and go to state 87 + + +State 64 + + 34 readStmt: "read" identsym • + + $default reduce using rule 34 (readStmt) + + +State 65 + + 35 printStmt: "print" expr • + 48 expr: expr • "+" term + 49 | expr • "-" term + + "+" shift, and go to state 76 + "-" shift, and go to state 77 + + $default reduce using rule 35 (printStmt) + + +State 66 + + 2 block: "begin" constDecls varDecls procDecls stmts "end" • + + $default reduce using rule 2 (block) + + +State 67 + + 21 stmtList: stmtList ";" • stmt + + identsym shift, and go to state 24 + "call" shift, and go to state 26 + "begin" shift, and go to state 1 + "if" shift, and go to state 27 + "while" shift, and go to state 28 + "read" shift, and go to state 29 + "print" shift, and go to state 30 + + block go to state 31 + stmt go to state 88 + assignStmt go to state 37 + callStmt go to state 38 + ifStmt go to state 39 + whileStmt go to state 40 + readStmt go to state 41 + printStmt go to state 42 + blockStmt go to state 43 + + +State 68 + + 14 identList: identList "," identsym • + + $default reduce using rule 14 (identList) + + +State 69 + + 29 assignStmt: identsym ":=" expr • + 48 expr: expr • "+" term + 49 | expr • "-" term + + "+" shift, and go to state 76 + "-" shift, and go to state 77 + + $default reduce using rule 29 (assignStmt) + + +State 70 + + 17 procDecl: "proc" identsym block • ";" + + ";" shift, and go to state 89 + + +State 71 + + 56 factor: "+" factor • + + $default reduce using rule 56 (factor) + + +State 72 + + 55 factor: "-" factor • + + $default reduce using rule 55 (factor) + + +State 73 + + 48 expr: expr • "+" term + 49 | expr • "-" term + 57 factor: "(" expr • ")" + + "+" shift, and go to state 76 + "-" shift, and go to state 77 + ")" shift, and go to state 90 + + +State 74 + + 39 dbCondition: "divisible" expr • "by" expr + 48 expr: expr • "+" term + 49 | expr • "-" term + + "+" shift, and go to state 76 + "-" shift, and go to state 77 + "by" shift, and go to state 91 + + +State 75 + + 31 ifStmt: "if" condition "then" • stmts "else" stmts "end" + 32 | "if" condition "then" • stmts "end" + + identsym shift, and go to state 24 + "call" shift, and go to state 26 + "begin" shift, and go to state 1 + "if" shift, and go to state 27 + "while" shift, and go to state 28 + "read" shift, and go to state 29 + "print" shift, and go to state 30 + + $default reduce using rule 5 (empty) + + block go to state 31 + empty go to state 32 + stmts go to state 92 + stmtList go to state 35 + stmt go to state 36 + assignStmt go to state 37 + callStmt go to state 38 + ifStmt go to state 39 + whileStmt go to state 40 + readStmt go to state 41 + printStmt go to state 42 + blockStmt go to state 43 + + +State 76 + + 48 expr: expr "+" • term + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + term go to state 93 + factor go to state 62 + + +State 77 + + 49 expr: expr "-" • term + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + term go to state 94 + factor go to state 62 + + +State 78 + + 41 relOp: "==" • + + $default reduce using rule 41 (relOp) + + +State 79 + + 42 relOp: "!=" • + + $default reduce using rule 42 (relOp) + + +State 80 + + 43 relOp: "<" • + + $default reduce using rule 43 (relOp) + + +State 81 + + 44 relOp: "<=" • + + $default reduce using rule 44 (relOp) + + +State 82 + + 45 relOp: ">" • + + $default reduce using rule 45 (relOp) + + +State 83 + + 46 relOp: ">=" • + + $default reduce using rule 46 (relOp) + + +State 84 + + 40 relOpCondition: expr relOp • expr + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + expr go to state 95 + term go to state 61 + factor go to state 62 + + +State 85 + + 51 term: term "*" • factor + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + factor go to state 96 + + +State 86 + + 52 term: term "/" • factor + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + factor go to state 97 + + +State 87 + + 33 whileStmt: "while" condition "do" • stmts "end" + + identsym shift, and go to state 24 + "call" shift, and go to state 26 + "begin" shift, and go to state 1 + "if" shift, and go to state 27 + "while" shift, and go to state 28 + "read" shift, and go to state 29 + "print" shift, and go to state 30 + + $default reduce using rule 5 (empty) + + block go to state 31 + empty go to state 32 + stmts go to state 98 + stmtList go to state 35 + stmt go to state 36 + assignStmt go to state 37 + callStmt go to state 38 + ifStmt go to state 39 + whileStmt go to state 40 + readStmt go to state 41 + printStmt go to state 42 + blockStmt go to state 43 + + +State 88 + + 21 stmtList: stmtList ";" stmt • + + $default reduce using rule 21 (stmtList) + + +State 89 + + 17 procDecl: "proc" identsym block ";" • + + $default reduce using rule 17 (procDecl) + + +State 90 + + 57 factor: "(" expr ")" • + + $default reduce using rule 57 (factor) + + +State 91 + + 39 dbCondition: "divisible" expr "by" • expr + + identsym shift, and go to state 51 + numbersym shift, and go to state 52 + "+" shift, and go to state 53 + "-" shift, and go to state 54 + "(" shift, and go to state 55 + + expr go to state 99 + term go to state 61 + factor go to state 62 + + +State 92 + + 31 ifStmt: "if" condition "then" stmts • "else" stmts "end" + 32 | "if" condition "then" stmts • "end" + + "end" shift, and go to state 100 + "else" shift, and go to state 101 + + +State 93 + + 48 expr: expr "+" term • + 51 term: term • "*" factor + 52 | term • "/" factor + + "*" shift, and go to state 85 + "/" shift, and go to state 86 + + $default reduce using rule 48 (expr) + + +State 94 + + 49 expr: expr "-" term • + 51 term: term • "*" factor + 52 | term • "/" factor + + "*" shift, and go to state 85 + "/" shift, and go to state 86 + + $default reduce using rule 49 (expr) + + +State 95 + + 40 relOpCondition: expr relOp expr • + 48 expr: expr • "+" term + 49 | expr • "-" term + + "+" shift, and go to state 76 + "-" shift, and go to state 77 + + $default reduce using rule 40 (relOpCondition) + + +State 96 + + 51 term: term "*" factor • + + $default reduce using rule 51 (term) + + +State 97 + + 52 term: term "/" factor • + + $default reduce using rule 52 (term) + + +State 98 + + 33 whileStmt: "while" condition "do" stmts • "end" + + "end" shift, and go to state 102 + + +State 99 + + 39 dbCondition: "divisible" expr "by" expr • + 48 expr: expr • "+" term + 49 | expr • "-" term + + "+" shift, and go to state 76 + "-" shift, and go to state 77 + + $default reduce using rule 39 (dbCondition) + + +State 100 + + 32 ifStmt: "if" condition "then" stmts "end" • + + $default reduce using rule 32 (ifStmt) + + +State 101 + + 31 ifStmt: "if" condition "then" stmts "else" • stmts "end" + + identsym shift, and go to state 24 + "call" shift, and go to state 26 + "begin" shift, and go to state 1 + "if" shift, and go to state 27 + "while" shift, and go to state 28 + "read" shift, and go to state 29 + "print" shift, and go to state 30 + + $default reduce using rule 5 (empty) + + block go to state 31 + empty go to state 32 + stmts go to state 103 + stmtList go to state 35 + stmt go to state 36 + assignStmt go to state 37 + callStmt go to state 38 + ifStmt go to state 39 + whileStmt go to state 40 + readStmt go to state 41 + printStmt go to state 42 + blockStmt go to state 43 + + +State 102 + + 33 whileStmt: "while" condition "do" stmts "end" • + + $default reduce using rule 33 (whileStmt) + + +State 103 + + 31 ifStmt: "if" condition "then" stmts "else" stmts • "end" + + "end" shift, and go to state 104 + + +State 104 + + 31 ifStmt: "if" condition "then" stmts "else" stmts "end" • + + $default reduce using rule 31 (ifStmt) diff --git a/spl.tab.c b/FromGithub/spl.tab.c old mode 100755 new mode 100644 similarity index 99% rename from spl.tab.c rename to FromGithub/spl.tab.c index f5865da..e123819 --- a/spl.tab.c +++ b/FromGithub/spl.tab.c @@ -65,8 +65,8 @@ /* "%code top" blocks. */ #line 3 "spl.y" - -#include + +#include #line 72 "spl.tab.c" @@ -173,16 +173,16 @@ typedef enum yysymbol_kind_t yysymbol_kind_t; /* Unqualified %code blocks. */ #line 106 "spl.y" - - /* extern declarations provided by the lexer */ -extern int yylex(void); - - /* The AST for the program, set by the semantic action - for the nonterminal program. */ -block_t progast; - - /* Set the program's ast to be t */ -extern void setProgAST(block_t t); + + /* extern declarations provided by the lexer */ +extern int yylex(void); + + /* The AST for the program, set by the semantic action + for the nonterminal program. */ +block_t progast; + + /* Set the program's ast to be t */ +extern void setProgAST(block_t t); #line 188 "spl.tab.c" @@ -1800,9 +1800,9 @@ yyparse (char const *file_name) case 6: /* empty: %empty */ #line 134 "spl.y" - { file_location *file_loc - = file_location_make(lexer_filename(), lexer_line()); - (yyval.empty) = ast_empty(file_loc); + { file_location *file_loc + = file_location_make(lexer_filename(), lexer_line()); + (yyval.empty) = ast_empty(file_loc); } #line 1808 "spl.tab.c" break; @@ -2313,7 +2313,7 @@ yyparse (char const *file_name) } #line 232 "spl.y" - - -// Set the program's ast to be ast -void setProgAST(block_t ast) { progast = ast; } + + +// Set the program's ast to be ast +void setProgAST(block_t ast) { progast = ast; } diff --git a/spl.tab.h b/FromGithub/spl.tab.h old mode 100755 new mode 100644 similarity index 99% rename from spl.tab.h rename to FromGithub/spl.tab.h index e147159..67e53e1 --- a/spl.tab.h +++ b/FromGithub/spl.tab.h @@ -46,17 +46,17 @@ extern int yydebug; #endif /* "%code requires" blocks. */ #line 7 "spl.y" - - - /* Including "ast.h" must be at the top, to define the AST type */ -#include "ast.h" -#include "machine_types.h" -#include "parser_types.h" -#include "lexer.h" - - /* Report an error to the user on stderr */ -extern void yyerror(const char *filename, const char *msg); - + + + /* Including "ast.h" must be at the top, to define the AST type */ +#include "ast.h" +#include "machine_types.h" +#include "parser_types.h" +#include "lexer.h" + + /* Report an error to the user on stderr */ +extern void yyerror(const char *filename, const char *msg); + #line 62 "spl.tab.h" diff --git a/FromGithub/spl.tab.o b/FromGithub/spl.tab.o new file mode 100644 index 0000000..da4b868 Binary files /dev/null and b/FromGithub/spl.tab.o differ diff --git a/spl.y b/FromGithub/spl.y old mode 100755 new mode 100644 similarity index 96% rename from spl.y rename to FromGithub/spl.y index 4549683..f8803cd --- a/spl.y +++ b/FromGithub/spl.y @@ -1,235 +1,235 @@ - /* $Id: spl.y,v 1.1 2024/10/23 12:17:38 leavens Exp $ */ - -%code top { -#include -} - -%code requires { - - /* Including "ast.h" must be at the top, to define the AST type */ -#include "ast.h" -#include "machine_types.h" -#include "parser_types.h" -#include "lexer.h" - - /* Report an error to the user on stderr */ -extern void yyerror(const char *filename, const char *msg); - -} /* end of %code requires */ - -%verbose -%define parse.lac full -%define parse.error detailed - - /* the following passes file_name to yyerror, - and declares it as an formal parameter of yyparse. */ -%parse-param { char const *file_name } - -%token identsym -%token numbersym -%token plussym "+" -%token minussym "-" -%token multsym "*" -%token divsym "/" - -%token periodsym "." -%token semisym ";" -%token eqsym "=" -%token commasym "," -%token becomessym ":=" -%token lparensym "(" -%token rparensym ")" - -%token constsym "const" -%token varsym "var" -%token procsym "proc" -%token callsym "call" -%token beginsym "begin" -%token endsym "end" -%token ifsym "if" -%token thensym "then" -%token elsesym "else" -%token whilesym "while" -%token dosym "do" -%token readsym "read" -%token printsym "print" -%token divisiblesym "divisible" -%token bysym "by" - -%token eqeqsym "==" -%token neqsym "!=" -%token ltsym "<" -%token leqsym "<=" -%token gtsym ">" -%token geqsym ">=" - -%type program - -%type block - -%type constDecls -%type constDecl -%type constDefList -%type constDef - -%type varDecls -%type varDecl -%type identList - -%type procDecls -%type procDecl - - -%type stmts -%type empty -%type stmtList -%type stmt -%type assignStmt -%type callStmt -%type ifStmt -%type whileStmt -%type readStmt -%type printStmt -%type blockStmt - -%type condition -%type dbCondition -%type relOpCondition -%type relOp - -%type expr -%type term -%type factor - -%start program - -%code { - /* extern declarations provided by the lexer */ -extern int yylex(void); - - /* The AST for the program, set by the semantic action - for the nonterminal program. */ -block_t progast; - - /* Set the program's ast to be t */ -extern void setProgAST(block_t t); -} - -%% - /* Write your grammar rules below and before the next %% */ - -program : block "." { setProgAST($1); } ; - - -block : "begin" constDecls varDecls procDecls stmts "end" - { $$ = ast_block($1,$2,$3,$4,$5); } - ; - -constDecls : empty { $$ = ast_const_decls_empty($1); } - | constDecls constDecl - { $$ = ast_const_decls($1, $2); } - ; - -empty : %empty - { file_location *file_loc - = file_location_make(lexer_filename(), lexer_line()); - $$ = ast_empty(file_loc); - } - ; - -constDecl : "const" constDefList ";" { $$ = ast_const_decl($2); } ; - -constDefList : constDef { $$ = ast_const_def_list_singleton($1); } - | constDefList "," constDef - { $$ = ast_const_def_list($1, $3); } - ; - -constDef : identsym "=" numbersym { $$ = ast_const_def($1, $3); } ; - -varDecls : empty { $$ = ast_var_decls_empty($1); } - | varDecls varDecl { $$ = ast_var_decls($1, $2); } - ; - -varDecl : "var" identList ";" { $$ = ast_var_decl($2); } ; - -identList : identsym { $$ = ast_ident_list_singleton($1); } - | identList "," identsym { $$ = ast_ident_list($1, $3); } - ; - -procDecls : empty { $$ = ast_proc_decls_empty($1); } - | procDecls procDecl { $$ = ast_proc_decls($1, $2); } - ; - -procDecl : "proc" identsym block ";" { $$ = ast_proc_decl($2, $3); } ; - -stmts : empty { $$ = ast_stmts_empty($1); } - | stmtList { $$ = ast_stmts($1); } - ; - -stmtList : stmt { $$ = ast_stmt_list_singleton($1); } - | stmtList ";" stmt { $$ = ast_stmt_list($1,$3); } - ; - -stmt : assignStmt { $$ = ast_stmt_assign($1); } - | callStmt { $$ = ast_stmt_call($1); } - | ifStmt { $$ = ast_stmt_if($1); } - | whileStmt { $$ = ast_stmt_while($1); } - | readStmt { $$ = ast_stmt_read($1); } - | printStmt { $$ = ast_stmt_print($1); } - | blockStmt { $$ = ast_stmt_block($1); } - ; - -assignStmt : identsym ":=" expr { $$ = ast_assign_stmt($1,$3); } ; - -callStmt : "call" identsym { $$ = ast_call_stmt($2); } ; - -ifStmt : "if" condition "then" stmts "else" stmts "end" - { $$ = ast_if_then_else_stmt($2, $4, $6); } - | "if" condition "then" stmts "end" - { $$ = ast_if_then_stmt($2, $4); } - ; - -whileStmt : "while" condition "do" stmts "end" - { $$ = ast_while_stmt($2,$4); } ; - -readStmt : "read" identsym { $$ = ast_read_stmt($2); } ; - -printStmt : "print" expr { $$ = ast_print_stmt($2); } ; - -blockStmt : block { $$ = ast_block_stmt($1); } ; - -condition : dbCondition { $$ = ast_condition_db($1); } - | relOpCondition { $$ = ast_condition_rel_op($1); } - ; - -dbCondition : "divisible" expr "by" expr { $$ = ast_db_condition($2,$4); } ; - -relOpCondition : expr relOp expr { $$ = ast_rel_op_condition($1, $2, $3); } ; - -relOp : "==" | "!=" | "<" | "<=" | ">" | ">=" ; - -expr : term - | expr "+" term - { $$ = ast_expr_binary_op(ast_binary_op_expr($1, $2, $3)); } - | expr "-" term - { $$ = ast_expr_binary_op(ast_binary_op_expr($1, $2, $3)); } - ; - -term : factor - | term "*" factor - { $$ = ast_expr_binary_op(ast_binary_op_expr($1, $2, $3)); } - | term "/" factor - { $$ = ast_expr_binary_op(ast_binary_op_expr($1, $2, $3)); } - ; - -factor : identsym { $$ = ast_expr_ident($1); } - | numbersym { $$ = ast_expr_number($1); } - | "-" factor { $$ = ast_expr_signed_expr($1, $2); } - | "+" factor { $$ = ast_expr_signed_expr($1, $2); } - | "(" expr ")" { $$ = $2; } - ; - -%% - -// Set the program's ast to be ast -void setProgAST(block_t ast) { progast = ast; } + /* $Id: spl.y,v 1.1 2024/10/23 12:17:38 leavens Exp $ */ + +%code top { +#include +} + +%code requires { + + /* Including "ast.h" must be at the top, to define the AST type */ +#include "ast.h" +#include "machine_types.h" +#include "parser_types.h" +#include "lexer.h" + + /* Report an error to the user on stderr */ +extern void yyerror(const char *filename, const char *msg); + +} /* end of %code requires */ + +%verbose +%define parse.lac full +%define parse.error detailed + + /* the following passes file_name to yyerror, + and declares it as an formal parameter of yyparse. */ +%parse-param { char const *file_name } + +%token identsym +%token numbersym +%token plussym "+" +%token minussym "-" +%token multsym "*" +%token divsym "/" + +%token periodsym "." +%token semisym ";" +%token eqsym "=" +%token commasym "," +%token becomessym ":=" +%token lparensym "(" +%token rparensym ")" + +%token constsym "const" +%token varsym "var" +%token procsym "proc" +%token callsym "call" +%token beginsym "begin" +%token endsym "end" +%token ifsym "if" +%token thensym "then" +%token elsesym "else" +%token whilesym "while" +%token dosym "do" +%token readsym "read" +%token printsym "print" +%token divisiblesym "divisible" +%token bysym "by" + +%token eqeqsym "==" +%token neqsym "!=" +%token ltsym "<" +%token leqsym "<=" +%token gtsym ">" +%token geqsym ">=" + +%type program + +%type block + +%type constDecls +%type constDecl +%type constDefList +%type constDef + +%type varDecls +%type varDecl +%type identList + +%type procDecls +%type procDecl + + +%type stmts +%type empty +%type stmtList +%type stmt +%type assignStmt +%type callStmt +%type ifStmt +%type whileStmt +%type readStmt +%type printStmt +%type blockStmt + +%type condition +%type dbCondition +%type relOpCondition +%type relOp + +%type expr +%type term +%type factor + +%start program + +%code { + /* extern declarations provided by the lexer */ +extern int yylex(void); + + /* The AST for the program, set by the semantic action + for the nonterminal program. */ +block_t progast; + + /* Set the program's ast to be t */ +extern void setProgAST(block_t t); +} + +%% + /* Write your grammar rules below and before the next %% */ + +program : block "." { setProgAST($1); } ; + + +block : "begin" constDecls varDecls procDecls stmts "end" + { $$ = ast_block($1,$2,$3,$4,$5); } + ; + +constDecls : empty { $$ = ast_const_decls_empty($1); } + | constDecls constDecl + { $$ = ast_const_decls($1, $2); } + ; + +empty : %empty + { file_location *file_loc + = file_location_make(lexer_filename(), lexer_line()); + $$ = ast_empty(file_loc); + } + ; + +constDecl : "const" constDefList ";" { $$ = ast_const_decl($2); } ; + +constDefList : constDef { $$ = ast_const_def_list_singleton($1); } + | constDefList "," constDef + { $$ = ast_const_def_list($1, $3); } + ; + +constDef : identsym "=" numbersym { $$ = ast_const_def($1, $3); } ; + +varDecls : empty { $$ = ast_var_decls_empty($1); } + | varDecls varDecl { $$ = ast_var_decls($1, $2); } + ; + +varDecl : "var" identList ";" { $$ = ast_var_decl($2); } ; + +identList : identsym { $$ = ast_ident_list_singleton($1); } + | identList "," identsym { $$ = ast_ident_list($1, $3); } + ; + +procDecls : empty { $$ = ast_proc_decls_empty($1); } + | procDecls procDecl { $$ = ast_proc_decls($1, $2); } + ; + +procDecl : "proc" identsym block ";" { $$ = ast_proc_decl($2, $3); } ; + +stmts : empty { $$ = ast_stmts_empty($1); } + | stmtList { $$ = ast_stmts($1); } + ; + +stmtList : stmt { $$ = ast_stmt_list_singleton($1); } + | stmtList ";" stmt { $$ = ast_stmt_list($1,$3); } + ; + +stmt : assignStmt { $$ = ast_stmt_assign($1); } + | callStmt { $$ = ast_stmt_call($1); } + | ifStmt { $$ = ast_stmt_if($1); } + | whileStmt { $$ = ast_stmt_while($1); } + | readStmt { $$ = ast_stmt_read($1); } + | printStmt { $$ = ast_stmt_print($1); } + | blockStmt { $$ = ast_stmt_block($1); } + ; + +assignStmt : identsym ":=" expr { $$ = ast_assign_stmt($1,$3); } ; + +callStmt : "call" identsym { $$ = ast_call_stmt($2); } ; + +ifStmt : "if" condition "then" stmts "else" stmts "end" + { $$ = ast_if_then_else_stmt($2, $4, $6); } + | "if" condition "then" stmts "end" + { $$ = ast_if_then_stmt($2, $4); } + ; + +whileStmt : "while" condition "do" stmts "end" + { $$ = ast_while_stmt($2,$4); } ; + +readStmt : "read" identsym { $$ = ast_read_stmt($2); } ; + +printStmt : "print" expr { $$ = ast_print_stmt($2); } ; + +blockStmt : block { $$ = ast_block_stmt($1); } ; + +condition : dbCondition { $$ = ast_condition_db($1); } + | relOpCondition { $$ = ast_condition_rel_op($1); } + ; + +dbCondition : "divisible" expr "by" expr { $$ = ast_db_condition($2,$4); } ; + +relOpCondition : expr relOp expr { $$ = ast_rel_op_condition($1, $2, $3); } ; + +relOp : "==" | "!=" | "<" | "<=" | ">" | ">=" ; + +expr : term + | expr "+" term + { $$ = ast_expr_binary_op(ast_binary_op_expr($1, $2, $3)); } + | expr "-" term + { $$ = ast_expr_binary_op(ast_binary_op_expr($1, $2, $3)); } + ; + +term : factor + | term "*" factor + { $$ = ast_expr_binary_op(ast_binary_op_expr($1, $2, $3)); } + | term "/" factor + { $$ = ast_expr_binary_op(ast_binary_op_expr($1, $2, $3)); } + ; + +factor : identsym { $$ = ast_expr_ident($1); } + | numbersym { $$ = ast_expr_number($1); } + | "-" factor { $$ = ast_expr_signed_expr($1, $2); } + | "+" factor { $$ = ast_expr_signed_expr($1, $2); } + | "(" expr ")" { $$ = $2; } + ; + +%% + +// Set the program's ast to be ast +void setProgAST(block_t ast) { progast = ast; } diff --git a/spl_lexer.c b/FromGithub/spl_lexer.c old mode 100755 new mode 100644 similarity index 99% rename from spl_lexer.c rename to FromGithub/spl_lexer.c index cbf6aa4..54a334b --- a/spl_lexer.c +++ b/FromGithub/spl_lexer.c @@ -1,6 +1,6 @@ -#line 1 "spl_lexer.c" +#line 2 "spl_lexer.c" -#line 3 "spl_lexer.c" +#line 4 "spl_lexer.c" #define YY_INT_ALIGNED short int @@ -535,80 +535,80 @@ int yy_flex_debug = 0; #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "spl_lexer.l" -/* $Id: spl_lexer.l,v 1.1 2024/10/23 12:17:38 leavens Exp $ */ -/* Lexical Analyzer for SPL */ +/* $Id: spl_lexer.l,v 1.1 2024/10/23 12:17:38 leavens Exp $ */ +/* Lexical Analyzer for SPL */ #line 10 "spl_lexer.l" -#include -#include -#include -#include -#include -#include "ast.h" -#include "parser_types.h" -#include "utilities.h" -#include "lexer.h" - - /* Tokens generated by Bison */ -#include "spl.tab.h" - - /* need declaration of fileno, part of the C standard library. - (Putting an extern declaration here shuts off a gcc warning.) */ -extern int fileno(FILE *stream); - -/* The filename of the file being read */ -static char *input_filename; - -/* Have any errors been noted? */ -static bool errors_noted; - -/* The value of a token */ -extern YYSTYPE yylval; - -/* The FILE used by the generated lexer */ -extern FILE *yyin; - -// We are not using yyunput or input -#define YY_NO_UNPUT -#define YY_NO_INPUT - -#undef yywrap /* sometimes a macro by default */ - -// apparently strdup is not declared in -extern char *strdup(const char *s); - -// set the lexer's value for a token in yylval as an AST -static void tok2ast(int code) { - AST t; - t.token.file_loc = file_location_make(input_filename, yylineno); - t.token.type_tag = token_ast; - t.token.code = code; - t.token.text = strdup(yytext); - yylval = t; -} - -static void ident2ast(const char *name) { - AST t; - assert(input_filename != NULL); - t.ident.file_loc = file_location_make(input_filename, yylineno); - t.ident.type_tag = ident_ast; - t.ident.name = strdup(name); - yylval = t; -} - -static void number2ast(unsigned int val) -{ - AST t; - t.number.file_loc = file_location_make(input_filename, yylineno); - t.number.type_tag = number_ast; - t.number.text = strdup(yytext); - t.number.value = val; - yylval = t; -} - -#line 608 "spl_lexer.c" +#include +#include +#include +#include +#include +#include "ast.h" +#include "parser_types.h" +#include "utilities.h" +#include "lexer.h" + + /* Tokens generated by Bison */ +#include "spl.tab.h" + + /* need declaration of fileno, part of the C standard library. + (Putting an extern declaration here shuts off a gcc warning.) */ +extern int fileno(FILE *stream); + +/* The filename of the file being read */ +static char *input_filename; + +/* Have any errors been noted? */ +static bool errors_noted; + +/* The value of a token */ +extern YYSTYPE yylval; + +/* The FILE used by the generated lexer */ +extern FILE *yyin; + +// We are not using yyunput or input +#define YY_NO_UNPUT +#define YY_NO_INPUT + +#undef yywrap /* sometimes a macro by default */ + +// apparently strdup is not declared in +extern char *strdup(const char *s); + +// set the lexer's value for a token in yylval as an AST +static void tok2ast(int code) { + AST t; + t.token.file_loc = file_location_make(input_filename, yylineno); + t.token.type_tag = token_ast; + t.token.code = code; + t.token.text = strdup(yytext); + yylval = t; +} + +static void ident2ast(const char *name) { + AST t; + assert(input_filename != NULL); + t.ident.file_loc = file_location_make(input_filename, yylineno); + t.ident.type_tag = ident_ast; + t.ident.name = strdup(name); + yylval = t; +} + +static void number2ast(unsigned int val) +{ + AST t; + t.number.file_loc = file_location_make(input_filename, yylineno); + t.number.type_tag = number_ast; + t.number.text = strdup(yytext); + t.number.value = val; + yylval = t; +} + +#line 609 "spl_lexer.c" #line 80 "spl_lexer.l" - /* you can add actual definitions below, before the %% */ -#line 611 "spl_lexer.c" + /* you can add actual definitions below, before the %% */ +#line 612 "spl_lexer.c" #define INITIAL 0 @@ -837,10 +837,10 @@ YY_DECL { #line 94 "spl_lexer.l" - - /* fill in the rules for your lexer here! */ - -#line 843 "spl_lexer.c" + + /* fill in the rules for your lexer here! */ + +#line 844 "spl_lexer.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -910,222 +910,222 @@ YY_DECL case 1: YY_RULE_SETUP #line 98 "spl_lexer.l" -{ ; } /* do nothing */ +{ ; } /* do nothing */ YY_BREAK case 2: YY_RULE_SETUP #line 99 "spl_lexer.l" -{ ; } /* ignore comments */ +{ ; } /* ignore comments */ YY_BREAK case 3: /* rule 3 can match eol */ YY_RULE_SETUP #line 100 "spl_lexer.l" -{ ; } /* ignore EOL */ +{ ; } /* ignore EOL */ YY_BREAK case 4: YY_RULE_SETUP #line 102 "spl_lexer.l" -{ unsigned long lval; - int ssf_ret; - ssf_ret = sscanf(yytext, "%lu", &lval); - if (ssf_ret != 1) { - bail_with_error("Number (%s) couldn't be read by lexer!", - yytext); - } - if (INT_MAX < lval ) { - char msgbuf[512]; - if (strlen(yytext) >= 300) { - snprintf(msgbuf, 327, "Number (%s...) is too large!", - yytext); - } else { - sprintf(msgbuf, "Number (%s) is too large!", yytext); - } - yyerror(lexer_filename(), msgbuf); - } - number2ast((int) lval); - return numbersym; - } +{ unsigned long lval; + int ssf_ret; + ssf_ret = sscanf(yytext, "%lu", &lval); + if (ssf_ret != 1) { + bail_with_error("Number (%s) couldn't be read by lexer!", + yytext); + } + if (INT_MAX < lval ) { + char msgbuf[512]; + if (strlen(yytext) >= 300) { + snprintf(msgbuf, 327, "Number (%s...) is too large!", + yytext); + } else { + sprintf(msgbuf, "Number (%s) is too large!", yytext); + } + yyerror(lexer_filename(), msgbuf); + } + number2ast((int) lval); + return numbersym; + } YY_BREAK case 5: YY_RULE_SETUP #line 123 "spl_lexer.l" -{ tok2ast(plussym); return plussym; } +{ tok2ast(plussym); return plussym; } YY_BREAK case 6: YY_RULE_SETUP #line 124 "spl_lexer.l" -{ tok2ast(minussym); return minussym; } +{ tok2ast(minussym); return minussym; } YY_BREAK case 7: YY_RULE_SETUP #line 125 "spl_lexer.l" -{ tok2ast(multsym); return multsym; } +{ tok2ast(multsym); return multsym; } YY_BREAK case 8: YY_RULE_SETUP #line 126 "spl_lexer.l" -{ tok2ast(divsym); return divsym; } +{ tok2ast(divsym); return divsym; } YY_BREAK case 9: YY_RULE_SETUP #line 128 "spl_lexer.l" -{ return periodsym; } +{ return periodsym; } YY_BREAK case 10: YY_RULE_SETUP #line 129 "spl_lexer.l" -{ return semisym; } +{ return semisym; } YY_BREAK case 11: YY_RULE_SETUP #line 130 "spl_lexer.l" -{ return commasym; } +{ return commasym; } YY_BREAK case 12: YY_RULE_SETUP #line 131 "spl_lexer.l" -{ return becomessym; } +{ return becomessym; } YY_BREAK case 13: YY_RULE_SETUP #line 132 "spl_lexer.l" -{ tok2ast(eqsym); return eqeqsym; } +{ tok2ast(eqsym); return eqeqsym; } YY_BREAK case 14: YY_RULE_SETUP #line 133 "spl_lexer.l" -{ tok2ast(eqsym); return eqsym; } +{ tok2ast(eqsym); return eqsym; } YY_BREAK case 15: YY_RULE_SETUP #line 134 "spl_lexer.l" -{ tok2ast(neqsym); return neqsym; } +{ tok2ast(neqsym); return neqsym; } YY_BREAK case 16: YY_RULE_SETUP #line 135 "spl_lexer.l" -{ tok2ast(leqsym); return leqsym; } +{ tok2ast(leqsym); return leqsym; } YY_BREAK case 17: YY_RULE_SETUP #line 136 "spl_lexer.l" -{ tok2ast(geqsym); return geqsym; } +{ tok2ast(geqsym); return geqsym; } YY_BREAK case 18: YY_RULE_SETUP #line 137 "spl_lexer.l" -{ tok2ast(gtsym); return gtsym; } +{ tok2ast(gtsym); return gtsym; } YY_BREAK case 19: YY_RULE_SETUP #line 138 "spl_lexer.l" -{ tok2ast(ltsym); return ltsym; } +{ tok2ast(ltsym); return ltsym; } YY_BREAK case 20: YY_RULE_SETUP #line 139 "spl_lexer.l" -{ tok2ast(lparensym); return lparensym; } +{ tok2ast(lparensym); return lparensym; } YY_BREAK case 21: YY_RULE_SETUP #line 140 "spl_lexer.l" -{ tok2ast(rparensym); return rparensym; } +{ tok2ast(rparensym); return rparensym; } YY_BREAK case 22: YY_RULE_SETUP #line 142 "spl_lexer.l" -{ tok2ast(constsym); return constsym; } +{ tok2ast(constsym); return constsym; } YY_BREAK case 23: YY_RULE_SETUP #line 143 "spl_lexer.l" -{ tok2ast(varsym); return varsym; } +{ tok2ast(varsym); return varsym; } YY_BREAK case 24: YY_RULE_SETUP #line 144 "spl_lexer.l" -{ tok2ast(procsym); return procsym; } +{ tok2ast(procsym); return procsym; } YY_BREAK case 25: YY_RULE_SETUP #line 145 "spl_lexer.l" -{ tok2ast(callsym); return callsym; } +{ tok2ast(callsym); return callsym; } YY_BREAK case 26: YY_RULE_SETUP #line 146 "spl_lexer.l" -{ tok2ast(beginsym); return beginsym; } +{ tok2ast(beginsym); return beginsym; } YY_BREAK case 27: YY_RULE_SETUP #line 147 "spl_lexer.l" -{ tok2ast(endsym); return endsym; } +{ tok2ast(endsym); return endsym; } YY_BREAK case 28: YY_RULE_SETUP #line 148 "spl_lexer.l" -{ tok2ast(ifsym); return ifsym; } +{ tok2ast(ifsym); return ifsym; } YY_BREAK case 29: YY_RULE_SETUP #line 149 "spl_lexer.l" -{ tok2ast(thensym); return thensym; } +{ tok2ast(thensym); return thensym; } YY_BREAK case 30: YY_RULE_SETUP #line 150 "spl_lexer.l" -{ tok2ast(elsesym); return elsesym; } +{ tok2ast(elsesym); return elsesym; } YY_BREAK case 31: YY_RULE_SETUP #line 151 "spl_lexer.l" -{ tok2ast(whilesym); return whilesym; } +{ tok2ast(whilesym); return whilesym; } YY_BREAK case 32: YY_RULE_SETUP #line 152 "spl_lexer.l" -{ tok2ast(dosym); return dosym; } +{ tok2ast(dosym); return dosym; } YY_BREAK case 33: YY_RULE_SETUP #line 153 "spl_lexer.l" -{ tok2ast(readsym); return readsym; } +{ tok2ast(readsym); return readsym; } YY_BREAK case 34: YY_RULE_SETUP #line 154 "spl_lexer.l" -{ tok2ast(printsym); return printsym; } +{ tok2ast(printsym); return printsym; } YY_BREAK case 35: YY_RULE_SETUP #line 155 "spl_lexer.l" -{ tok2ast(divisiblesym); return divisiblesym; } +{ tok2ast(divisiblesym); return divisiblesym; } YY_BREAK case 36: YY_RULE_SETUP #line 156 "spl_lexer.l" -{ tok2ast(bysym); return bysym; } +{ tok2ast(bysym); return bysym; } YY_BREAK case 37: YY_RULE_SETUP #line 158 "spl_lexer.l" -{ ident2ast(yytext); return identsym; } +{ ident2ast(yytext); return identsym; } YY_BREAK case 38: YY_RULE_SETUP #line 160 "spl_lexer.l" -{ char msgbuf[512]; - sprintf(msgbuf, "invalid character: '%c' ('\\0%o')", *yytext, *yytext); - yyerror(lexer_filename(), msgbuf); - } +{ char msgbuf[512]; + sprintf(msgbuf, "invalid character: '%c' ('\\0%o')", *yytext, *yytext); + yyerror(lexer_filename(), msgbuf); + } YY_BREAK case 39: YY_RULE_SETUP #line 164 "spl_lexer.l" ECHO; YY_BREAK -#line 1128 "spl_lexer.c" +#line 1129 "spl_lexer.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -2144,93 +2144,93 @@ void yyfree (void * ptr ) #line 164 "spl_lexer.l" - - /* This code goes in the user code section of the spl_lexer.l file, - following the last %% above. */ - -// Requires: fname != NULL -// Requires: fname is the name of a readable file -// Initialize the lexer and start it reading -// from the given file name -void lexer_init(char *fname) -{ - errors_noted = false; - yyin = fopen(fname, "r"); - if (yyin == NULL) { - bail_with_error("Cannot open %s", fname); - } - input_filename = fname; -} - -// Close the file yyin -// and return 0 to indicate that there are no more files -int yywrap() { - if (yyin != NULL) { - int rc = fclose(yyin); - if (rc == EOF) { - bail_with_error("Cannot close %s!", input_filename); - } - } - input_filename = NULL; - return 1; /* no more input */ -} - -// Return the name of the current input file -const char *lexer_filename() { - return input_filename; -} - -// Return the line number of the next token -unsigned int lexer_line() { - return yylineno; -} - -/* Report an error to the user on stderr */ -void yyerror(const char *filename, const char *msg) -{ - fflush(stdout); - fprintf(stderr, "%s:%d: %s\n", input_filename, lexer_line(), msg); - errors_noted = true; -} - -// On standard output: -// Print a message about the file name of the lexer's input -// and then print a heading for the lexer's output. -void lexer_print_output_header() -{ - printf("Tokens from file %s\n", lexer_filename()); - printf("%-6s %-4s %s\n", "Number", "Line", "Text"); -} - -// Have any errors been noted by the lexer? -bool lexer_has_errors() -{ - return errors_noted; -} - -// Print information about the token t to stdout -// followed by a newline -void lexer_print_token(enum yytokentype t, unsigned int tline, - const char *txt) -{ - printf("%-6d %-4d \"%s\"\n", t, tline, txt); -} - - -/* Read all the tokens from the input file - * and print each token on standard output - * using the format in lexer_print_token */ -void lexer_output() -{ - lexer_print_output_header(); - AST dummy; - yytoken_kind_t t; - do { - t = yylex(&dummy); - if (t == YYEOF) { - break; - } - lexer_print_token(t, yylineno, yytext); - } while (t != YYEOF); -} + + /* This code goes in the user code section of the spl_lexer.l file, + following the last %% above. */ + +// Requires: fname != NULL +// Requires: fname is the name of a readable file +// Initialize the lexer and start it reading +// from the given file name +void lexer_init(char *fname) +{ + errors_noted = false; + yyin = fopen(fname, "r"); + if (yyin == NULL) { + bail_with_error("Cannot open %s", fname); + } + input_filename = fname; +} + +// Close the file yyin +// and return 0 to indicate that there are no more files +int yywrap() { + if (yyin != NULL) { + int rc = fclose(yyin); + if (rc == EOF) { + bail_with_error("Cannot close %s!", input_filename); + } + } + input_filename = NULL; + return 1; /* no more input */ +} + +// Return the name of the current input file +const char *lexer_filename() { + return input_filename; +} + +// Return the line number of the next token +unsigned int lexer_line() { + return yylineno; +} + +/* Report an error to the user on stderr */ +void yyerror(const char *filename, const char *msg) +{ + fflush(stdout); + fprintf(stderr, "%s:%d: %s\n", input_filename, lexer_line(), msg); + errors_noted = true; +} + +// On standard output: +// Print a message about the file name of the lexer's input +// and then print a heading for the lexer's output. +void lexer_print_output_header() +{ + printf("Tokens from file %s\n", lexer_filename()); + printf("%-6s %-4s %s\n", "Number", "Line", "Text"); +} + +// Have any errors been noted by the lexer? +bool lexer_has_errors() +{ + return errors_noted; +} + +// Print information about the token t to stdout +// followed by a newline +void lexer_print_token(enum yytokentype t, unsigned int tline, + const char *txt) +{ + printf("%-6d %-4d \"%s\"\n", t, tline, txt); +} + + +/* Read all the tokens from the input file + * and print each token on standard output + * using the format in lexer_print_token */ +void lexer_output() +{ + lexer_print_output_header(); + AST dummy; + yytoken_kind_t t; + do { + t = yylex(&dummy); + if (t == YYEOF) { + break; + } + lexer_print_token(t, yylineno, yytext); + } while (t != YYEOF); +} diff --git a/spl_lexer.h b/FromGithub/spl_lexer.h old mode 100755 new mode 100644 similarity index 99% rename from spl_lexer.h rename to FromGithub/spl_lexer.h index c3c120d..a0e11df --- a/spl_lexer.h +++ b/FromGithub/spl_lexer.h @@ -2,9 +2,9 @@ #define yyHEADER_H 1 #define yyIN_HEADER 1 -#line 5 "spl_lexer.h" +#line 6 "spl_lexer.h" -#line 7 "spl_lexer.h" +#line 8 "spl_lexer.h" #define YY_INT_ALIGNED short int @@ -487,6 +487,6 @@ extern int yylex \ #line 164 "spl_lexer.l" -#line 490 "spl_lexer.h" +#line 491 "spl_lexer.h" #undef yyIN_HEADER #endif /* yyHEADER_H */ diff --git a/spl_lexer.l b/FromGithub/spl_lexer.l old mode 100755 new mode 100644 similarity index 96% rename from spl_lexer.l rename to FromGithub/spl_lexer.l index 55ca4a3..9a79bac --- a/spl_lexer.l +++ b/FromGithub/spl_lexer.l @@ -1,252 +1,252 @@ -/* $Id: spl_lexer.l,v 1.1 2024/10/23 12:17:38 leavens Exp $ */ -/* Lexical Analyzer for SPL */ - -%option header-file = "spl_lexer.h" -%option outfile = "spl_lexer.c" -%option yylineno -%option bison-bridge - -%{ -#include -#include -#include -#include -#include -#include "ast.h" -#include "parser_types.h" -#include "utilities.h" -#include "lexer.h" - - /* Tokens generated by Bison */ -#include "spl.tab.h" - - /* need declaration of fileno, part of the C standard library. - (Putting an extern declaration here shuts off a gcc warning.) */ -extern int fileno(FILE *stream); - -/* The filename of the file being read */ -static char *input_filename; - -/* Have any errors been noted? */ -static bool errors_noted; - -/* The value of a token */ -extern YYSTYPE yylval; - -/* The FILE used by the generated lexer */ -extern FILE *yyin; - -// We are not using yyunput or input -#define YY_NO_UNPUT -#define YY_NO_INPUT - -#undef yywrap /* sometimes a macro by default */ - -// apparently strdup is not declared in -extern char *strdup(const char *s); - -// set the lexer's value for a token in yylval as an AST -static void tok2ast(int code) { - AST t; - t.token.file_loc = file_location_make(input_filename, yylineno); - t.token.type_tag = token_ast; - t.token.code = code; - t.token.text = strdup(yytext); - yylval = t; -} - -static void ident2ast(const char *name) { - AST t; - assert(input_filename != NULL); - t.ident.file_loc = file_location_make(input_filename, yylineno); - t.ident.type_tag = ident_ast; - t.ident.name = strdup(name); - yylval = t; -} - -static void number2ast(unsigned int val) -{ - AST t; - t.number.file_loc = file_location_make(input_filename, yylineno); - t.number.type_tag = number_ast; - t.number.text = strdup(yytext); - t.number.value = val; - yylval = t; -} - -%} - - /* you can add actual definitions below, before the %% */ - -DIGIT [0-9] -NUMBER {DIGIT}+ -LETTER [a-zA-Z] -LETTERORDIGIT ({LETTER}|{DIGIT}) -IDENT {LETTER}({LETTERORDIGIT}*) -NEWLINE \n -CR \r -EOL ({NEWLINE}|({CR}{NEWLINE})) -COMMENTSTART % -COMMENT {COMMENTSTART}.* -IGNORED [ \t\v\f\r] - -%% - - /* fill in the rules for your lexer here! */ - -{IGNORED} { ; } /* do nothing */ -{COMMENT} { ; } /* ignore comments */ -{EOL} { ; } /* ignore EOL */ - -{NUMBER} { unsigned long lval; - int ssf_ret; - ssf_ret = sscanf(yytext, "%lu", &lval); - if (ssf_ret != 1) { - bail_with_error("Number (%s) couldn't be read by lexer!", - yytext); - } - if (INT_MAX < lval ) { - char msgbuf[512]; - if (strlen(yytext) >= 300) { - snprintf(msgbuf, 327, "Number (%s...) is too large!", - yytext); - } else { - sprintf(msgbuf, "Number (%s) is too large!", yytext); - } - yyerror(lexer_filename(), msgbuf); - } - number2ast((int) lval); - return numbersym; - } - -\+ { tok2ast(plussym); return plussym; } -- { tok2ast(minussym); return minussym; } -\* { tok2ast(multsym); return multsym; } -\/ { tok2ast(divsym); return divsym; } - -\. { return periodsym; } -\; { return semisym; } -, { return commasym; } -:= { return becomessym; } -== { tok2ast(eqsym); return eqeqsym; } -= { tok2ast(eqsym); return eqsym; } -!= { tok2ast(neqsym); return neqsym; } -\<= { tok2ast(leqsym); return leqsym; } -\>= { tok2ast(geqsym); return geqsym; } -\> { tok2ast(gtsym); return gtsym; } -\< { tok2ast(ltsym); return ltsym; } -\( { tok2ast(lparensym); return lparensym; } -\) { tok2ast(rparensym); return rparensym; } - -const { tok2ast(constsym); return constsym; } -var { tok2ast(varsym); return varsym; } -proc { tok2ast(procsym); return procsym; } -call { tok2ast(callsym); return callsym; } -begin { tok2ast(beginsym); return beginsym; } -end { tok2ast(endsym); return endsym; } -if { tok2ast(ifsym); return ifsym; } -then { tok2ast(thensym); return thensym; } -else { tok2ast(elsesym); return elsesym; } -while { tok2ast(whilesym); return whilesym; } -do { tok2ast(dosym); return dosym; } -read { tok2ast(readsym); return readsym; } -print { tok2ast(printsym); return printsym; } -divisible { tok2ast(divisiblesym); return divisiblesym; } -by { tok2ast(bysym); return bysym; } - -{IDENT} { ident2ast(yytext); return identsym; } - -. { char msgbuf[512]; - sprintf(msgbuf, "invalid character: '%c' ('\\0%o')", *yytext, *yytext); - yyerror(lexer_filename(), msgbuf); - } -%% - - /* This code goes in the user code section of the spl_lexer.l file, - following the last %% above. */ - -// Requires: fname != NULL -// Requires: fname is the name of a readable file -// Initialize the lexer and start it reading -// from the given file name -void lexer_init(char *fname) -{ - errors_noted = false; - yyin = fopen(fname, "r"); - if (yyin == NULL) { - bail_with_error("Cannot open %s", fname); - } - input_filename = fname; -} - -// Close the file yyin -// and return 0 to indicate that there are no more files -int yywrap() { - if (yyin != NULL) { - int rc = fclose(yyin); - if (rc == EOF) { - bail_with_error("Cannot close %s!", input_filename); - } - } - input_filename = NULL; - return 1; /* no more input */ -} - -// Return the name of the current input file -const char *lexer_filename() { - return input_filename; -} - -// Return the line number of the next token -unsigned int lexer_line() { - return yylineno; -} - -/* Report an error to the user on stderr */ -void yyerror(const char *filename, const char *msg) -{ - fflush(stdout); - fprintf(stderr, "%s:%d: %s\n", input_filename, lexer_line(), msg); - errors_noted = true; -} - -// On standard output: -// Print a message about the file name of the lexer's input -// and then print a heading for the lexer's output. -void lexer_print_output_header() -{ - printf("Tokens from file %s\n", lexer_filename()); - printf("%-6s %-4s %s\n", "Number", "Line", "Text"); -} - -// Have any errors been noted by the lexer? -bool lexer_has_errors() -{ - return errors_noted; -} - -// Print information about the token t to stdout -// followed by a newline -void lexer_print_token(enum yytokentype t, unsigned int tline, - const char *txt) -{ - printf("%-6d %-4d \"%s\"\n", t, tline, txt); -} - - -/* Read all the tokens from the input file - * and print each token on standard output - * using the format in lexer_print_token */ -void lexer_output() -{ - lexer_print_output_header(); - AST dummy; - yytoken_kind_t t; - do { - t = yylex(&dummy); - if (t == YYEOF) { - break; - } - lexer_print_token(t, yylineno, yytext); - } while (t != YYEOF); -} +/* $Id: spl_lexer.l,v 1.1 2024/10/23 12:17:38 leavens Exp $ */ +/* Lexical Analyzer for SPL */ + +%option header-file = "spl_lexer.h" +%option outfile = "spl_lexer.c" +%option yylineno +%option bison-bridge + +%{ +#include +#include +#include +#include +#include +#include "ast.h" +#include "parser_types.h" +#include "utilities.h" +#include "lexer.h" + + /* Tokens generated by Bison */ +#include "spl.tab.h" + + /* need declaration of fileno, part of the C standard library. + (Putting an extern declaration here shuts off a gcc warning.) */ +extern int fileno(FILE *stream); + +/* The filename of the file being read */ +static char *input_filename; + +/* Have any errors been noted? */ +static bool errors_noted; + +/* The value of a token */ +extern YYSTYPE yylval; + +/* The FILE used by the generated lexer */ +extern FILE *yyin; + +// We are not using yyunput or input +#define YY_NO_UNPUT +#define YY_NO_INPUT + +#undef yywrap /* sometimes a macro by default */ + +// apparently strdup is not declared in +extern char *strdup(const char *s); + +// set the lexer's value for a token in yylval as an AST +static void tok2ast(int code) { + AST t; + t.token.file_loc = file_location_make(input_filename, yylineno); + t.token.type_tag = token_ast; + t.token.code = code; + t.token.text = strdup(yytext); + yylval = t; +} + +static void ident2ast(const char *name) { + AST t; + assert(input_filename != NULL); + t.ident.file_loc = file_location_make(input_filename, yylineno); + t.ident.type_tag = ident_ast; + t.ident.name = strdup(name); + yylval = t; +} + +static void number2ast(unsigned int val) +{ + AST t; + t.number.file_loc = file_location_make(input_filename, yylineno); + t.number.type_tag = number_ast; + t.number.text = strdup(yytext); + t.number.value = val; + yylval = t; +} + +%} + + /* you can add actual definitions below, before the %% */ + +DIGIT [0-9] +NUMBER {DIGIT}+ +LETTER [a-zA-Z] +LETTERORDIGIT ({LETTER}|{DIGIT}) +IDENT {LETTER}({LETTERORDIGIT}*) +NEWLINE \n +CR \r +EOL ({NEWLINE}|({CR}{NEWLINE})) +COMMENTSTART % +COMMENT {COMMENTSTART}.* +IGNORED [ \t\v\f\r] + +%% + + /* fill in the rules for your lexer here! */ + +{IGNORED} { ; } /* do nothing */ +{COMMENT} { ; } /* ignore comments */ +{EOL} { ; } /* ignore EOL */ + +{NUMBER} { unsigned long lval; + int ssf_ret; + ssf_ret = sscanf(yytext, "%lu", &lval); + if (ssf_ret != 1) { + bail_with_error("Number (%s) couldn't be read by lexer!", + yytext); + } + if (INT_MAX < lval ) { + char msgbuf[512]; + if (strlen(yytext) >= 300) { + snprintf(msgbuf, 327, "Number (%s...) is too large!", + yytext); + } else { + sprintf(msgbuf, "Number (%s) is too large!", yytext); + } + yyerror(lexer_filename(), msgbuf); + } + number2ast((int) lval); + return numbersym; + } + +\+ { tok2ast(plussym); return plussym; } +- { tok2ast(minussym); return minussym; } +\* { tok2ast(multsym); return multsym; } +\/ { tok2ast(divsym); return divsym; } + +\. { return periodsym; } +\; { return semisym; } +, { return commasym; } +:= { return becomessym; } +== { tok2ast(eqsym); return eqeqsym; } += { tok2ast(eqsym); return eqsym; } +!= { tok2ast(neqsym); return neqsym; } +\<= { tok2ast(leqsym); return leqsym; } +\>= { tok2ast(geqsym); return geqsym; } +\> { tok2ast(gtsym); return gtsym; } +\< { tok2ast(ltsym); return ltsym; } +\( { tok2ast(lparensym); return lparensym; } +\) { tok2ast(rparensym); return rparensym; } + +const { tok2ast(constsym); return constsym; } +var { tok2ast(varsym); return varsym; } +proc { tok2ast(procsym); return procsym; } +call { tok2ast(callsym); return callsym; } +begin { tok2ast(beginsym); return beginsym; } +end { tok2ast(endsym); return endsym; } +if { tok2ast(ifsym); return ifsym; } +then { tok2ast(thensym); return thensym; } +else { tok2ast(elsesym); return elsesym; } +while { tok2ast(whilesym); return whilesym; } +do { tok2ast(dosym); return dosym; } +read { tok2ast(readsym); return readsym; } +print { tok2ast(printsym); return printsym; } +divisible { tok2ast(divisiblesym); return divisiblesym; } +by { tok2ast(bysym); return bysym; } + +{IDENT} { ident2ast(yytext); return identsym; } + +. { char msgbuf[512]; + sprintf(msgbuf, "invalid character: '%c' ('\\0%o')", *yytext, *yytext); + yyerror(lexer_filename(), msgbuf); + } +%% + + /* This code goes in the user code section of the spl_lexer.l file, + following the last %% above. */ + +// Requires: fname != NULL +// Requires: fname is the name of a readable file +// Initialize the lexer and start it reading +// from the given file name +void lexer_init(char *fname) +{ + errors_noted = false; + yyin = fopen(fname, "r"); + if (yyin == NULL) { + bail_with_error("Cannot open %s", fname); + } + input_filename = fname; +} + +// Close the file yyin +// and return 0 to indicate that there are no more files +int yywrap() { + if (yyin != NULL) { + int rc = fclose(yyin); + if (rc == EOF) { + bail_with_error("Cannot close %s!", input_filename); + } + } + input_filename = NULL; + return 1; /* no more input */ +} + +// Return the name of the current input file +const char *lexer_filename() { + return input_filename; +} + +// Return the line number of the next token +unsigned int lexer_line() { + return yylineno; +} + +/* Report an error to the user on stderr */ +void yyerror(const char *filename, const char *msg) +{ + fflush(stdout); + fprintf(stderr, "%s:%d: %s\n", input_filename, lexer_line(), msg); + errors_noted = true; +} + +// On standard output: +// Print a message about the file name of the lexer's input +// and then print a heading for the lexer's output. +void lexer_print_output_header() +{ + printf("Tokens from file %s\n", lexer_filename()); + printf("%-6s %-4s %s\n", "Number", "Line", "Text"); +} + +// Have any errors been noted by the lexer? +bool lexer_has_errors() +{ + return errors_noted; +} + +// Print information about the token t to stdout +// followed by a newline +void lexer_print_token(enum yytokentype t, unsigned int tline, + const char *txt) +{ + printf("%-6d %-4d \"%s\"\n", t, tline, txt); +} + + +/* Read all the tokens from the input file + * and print each token on standard output + * using the format in lexer_print_token */ +void lexer_output() +{ + lexer_print_output_header(); + AST dummy; + yytoken_kind_t t; + do { + t = yylex(&dummy); + if (t == YYEOF) { + break; + } + lexer_print_token(t, yylineno, yytext); + } while (t != YYEOF); +} diff --git a/FromGithub/spl_lexer.o b/FromGithub/spl_lexer.o new file mode 100644 index 0000000..a257ff7 Binary files /dev/null and b/FromGithub/spl_lexer.o differ diff --git a/symtab.c b/FromGithub/symtab.c old mode 100755 new mode 100644 similarity index 96% rename from symtab.c rename to FromGithub/symtab.c index 4e2cd57..fc00ab4 --- a/symtab.c +++ b/FromGithub/symtab.c @@ -1,169 +1,169 @@ -/* $Id: symtab.c,v 1.9 2024/11/10 22:48:40 leavens Exp $ */ -#include -#include "symtab.h" -#include "scope.h" -#include "utilities.h" - -// The symbol table is a stack of scope (see the scope module). - -// index of the top of the stack of scopes -static int symtab_top_idx = -1; - -// the symbol table itself -static scope_t *symtab[MAX_NESTING]; - -// initialize the symbol table -void symtab_initialize() -{ - // initialize the internal state - symtab_top_idx = -1; - for (int i = 0; i < MAX_NESTING; i++) { - symtab[i] = NULL; - } -} - -// Return the number of scopes currently in the symbol table. -unsigned int symtab_size() -{ - return symtab_top_idx + 1; -} - -// Does this symbol table have any scopes in it? -bool symtab_empty() -{ - return symtab_size() == 0; -} - -// Return the current scope's next location count -// (of constants and variables). -unsigned int symtab_scope_loc_count() -{ - return scope_loc_count(symtab[symtab_top_idx]); -} - -// Return the current scope's size (the number of declared ids). -unsigned int symtab_scope_size() -{ - return scope_size(symtab[symtab_top_idx]); -} - -// Is the current scope full? -bool symtab_scope_full() -{ - return scope_full(symtab[symtab_top_idx]); -} - -// Return the current nesting level of the symbol table -// (this is the number of (client made) symtab_enter_scope() calls -// minus the number of symtab_leave_scope() calls -unsigned int symtab_current_nesting_level() -{ - // assert(symtab_top_idx >= 0); - return symtab_top_idx; -} - -// Is the symbol table itself full -// (i.e., is symtab_current_nesting_level() equal to MAX_NESTING-1)? -bool symtab_full() -{ - return symtab_current_nesting_level() == MAX_NESTING - 1; -} - -// Is the given name associated with some attributes? -// (this looks back through all scopes). -bool symtab_defined(const char *name) -{ - return symtab_lookup(name) != NULL; -} - -// Is the given name associated with some attributes in the current scope? -// (this only looks in the current scope). -bool symtab_defined_in_current_scope(const char *name) -{ - id_attrs *attrs = scope_lookup(symtab[symtab_top_idx], name); - return attrs != NULL; -} - - -// Put the given name, which is to be declared with kind k, -// and has its declaration at the given file location (floc), -// into the current scope's symbol table at the offset scope_next_offset(). -static void add_ident(scope_t *s, const char*name, id_attrs *attrs) -{ - id_attrs *old_attrs = scope_lookup(s, name); - if (old_attrs != NULL) { - bail_with_prog_error(attrs->file_loc, - "%s \"%s\" is already declared as a %s", - id_attrs_id_kind_string(attrs->kind), name, - id_attrs_id_kind_string(old_attrs->kind)); - } else { - scope_insert(s, name, attrs); - } -} - -// Requires: !symtab_defined(name) && attrs != NULL -// Modify the current scope (as recorded in the symbol table) to -// add an association from the given name to attributes appropriate -// for k and floc. -void symtab_insert(const char *name, id_attrs *attrs) -{ - add_ident(symtab[symtab_top_idx], name, attrs); -} - -// Requires: !symtab_full() -// Start a new scope (for a procedure) -void symtab_enter_scope() -{ - symtab_top_idx++; - symtab[symtab_top_idx] = scope_create(); -} - -// Requires: !symtab_empty() -void symtab_leave_scope() -{ - if (symtab_top_idx < 0) { - bail_with_error("Cannot leave scope, no scope on symtab's stack!"); - } - symtab_top_idx--; -} - -// Return (a pointer to) the attributes of the given name -// or NULL if there is no association for name in the symbol table. -// (this looks back through all scopes). -id_use *symtab_lookup(const char *name) -{ - unsigned int levelsOut = 0; - for (int level = symtab_top_idx; 0 <= level; level--) { - id_attrs *attrs = scope_lookup(symtab[level], name); - if (attrs != NULL) { - // debug_print("symtab_lookup returning with levelsOut == %d for %s\n", - // levelsOut, name); - return id_use_create(attrs, levelsOut); - } - levelsOut++; - } - return NULL; -} - -// We'll use lexical addresses in HW4... -// Requires: symtab_defined(name) -// Return (a pointer to) the lexical address of the given name -// or NULL if there is no association for name. -/* -lexical_address *symtab_lexical_address(const char *name) -{ - // maintaining: -1 <= level <= symtab_top_idx; - // maintaining: (for all int j: - // level < j <= symtab_top_idx - // ==> !scope_defined(symtab[j], name)) - for (int level = symtab_top_idx; 0 <= level; level--) { - id_attrs *attrs = scope_lookup(symtab[level], name); - if (attrs != NULL) { - return lexical_address_create(symtab_top_idx - level, - attrs->loc_offset); - } - } - bail_with_error("Couldn't find %s for symtab_lexical_address!", name); - return NULL; -} -*/ +/* $Id: symtab.c,v 1.9 2024/11/10 22:48:40 leavens Exp $ */ +#include +#include "symtab.h" +#include "scope.h" +#include "utilities.h" + +// The symbol table is a stack of scope (see the scope module). + +// index of the top of the stack of scopes +static int symtab_top_idx = -1; + +// the symbol table itself +static scope_t *symtab[MAX_NESTING]; + +// initialize the symbol table +void symtab_initialize() +{ + // initialize the internal state + symtab_top_idx = -1; + for (int i = 0; i < MAX_NESTING; i++) { + symtab[i] = NULL; + } +} + +// Return the number of scopes currently in the symbol table. +unsigned int symtab_size() +{ + return symtab_top_idx + 1; +} + +// Does this symbol table have any scopes in it? +bool symtab_empty() +{ + return symtab_size() == 0; +} + +// Return the current scope's next location count +// (of constants and variables). +unsigned int symtab_scope_loc_count() +{ + return scope_loc_count(symtab[symtab_top_idx]); +} + +// Return the current scope's size (the number of declared ids). +unsigned int symtab_scope_size() +{ + return scope_size(symtab[symtab_top_idx]); +} + +// Is the current scope full? +bool symtab_scope_full() +{ + return scope_full(symtab[symtab_top_idx]); +} + +// Return the current nesting level of the symbol table +// (this is the number of (client made) symtab_enter_scope() calls +// minus the number of symtab_leave_scope() calls +unsigned int symtab_current_nesting_level() +{ + // assert(symtab_top_idx >= 0); + return symtab_top_idx; +} + +// Is the symbol table itself full +// (i.e., is symtab_current_nesting_level() equal to MAX_NESTING-1)? +bool symtab_full() +{ + return symtab_current_nesting_level() == MAX_NESTING - 1; +} + +// Is the given name associated with some attributes? +// (this looks back through all scopes). +bool symtab_defined(const char *name) +{ + return symtab_lookup(name) != NULL; +} + +// Is the given name associated with some attributes in the current scope? +// (this only looks in the current scope). +bool symtab_defined_in_current_scope(const char *name) +{ + id_attrs *attrs = scope_lookup(symtab[symtab_top_idx], name); + return attrs != NULL; +} + + +// Put the given name, which is to be declared with kind k, +// and has its declaration at the given file location (floc), +// into the current scope's symbol table at the offset scope_next_offset(). +static void add_ident(scope_t *s, const char*name, id_attrs *attrs) +{ + id_attrs *old_attrs = scope_lookup(s, name); + if (old_attrs != NULL) { + bail_with_prog_error(attrs->file_loc, + "%s \"%s\" is already declared as a %s", + id_attrs_id_kind_string(attrs->kind), name, + id_attrs_id_kind_string(old_attrs->kind)); + } else { + scope_insert(s, name, attrs); + } +} + +// Requires: !symtab_defined(name) && attrs != NULL +// Modify the current scope (as recorded in the symbol table) to +// add an association from the given name to attributes appropriate +// for k and floc. +void symtab_insert(const char *name, id_attrs *attrs) +{ + add_ident(symtab[symtab_top_idx], name, attrs); +} + +// Requires: !symtab_full() +// Start a new scope (for a procedure) +void symtab_enter_scope() +{ + symtab_top_idx++; + symtab[symtab_top_idx] = scope_create(); +} + +// Requires: !symtab_empty() +void symtab_leave_scope() +{ + if (symtab_top_idx < 0) { + bail_with_error("Cannot leave scope, no scope on symtab's stack!"); + } + symtab_top_idx--; +} + +// Return (a pointer to) the attributes of the given name +// or NULL if there is no association for name in the symbol table. +// (this looks back through all scopes). +id_use *symtab_lookup(const char *name) +{ + unsigned int levelsOut = 0; + for (int level = symtab_top_idx; 0 <= level; level--) { + id_attrs *attrs = scope_lookup(symtab[level], name); + if (attrs != NULL) { + // debug_print("symtab_lookup returning with levelsOut == %d for %s\n", + // levelsOut, name); + return id_use_create(attrs, levelsOut); + } + levelsOut++; + } + return NULL; +} + +// We'll use lexical addresses in HW4... +// Requires: symtab_defined(name) +// Return (a pointer to) the lexical address of the given name +// or NULL if there is no association for name. +/* +lexical_address *symtab_lexical_address(const char *name) +{ + // maintaining: -1 <= level <= symtab_top_idx; + // maintaining: (for all int j: + // level < j <= symtab_top_idx + // ==> !scope_defined(symtab[j], name)) + for (int level = symtab_top_idx; 0 <= level; level--) { + id_attrs *attrs = scope_lookup(symtab[level], name); + if (attrs != NULL) { + return lexical_address_create(symtab_top_idx - level, + attrs->loc_offset); + } + } + bail_with_error("Couldn't find %s for symtab_lexical_address!", name); + return NULL; +} +*/ diff --git a/symtab.h b/FromGithub/symtab.h old mode 100755 new mode 100644 similarity index 97% rename from symtab.h rename to FromGithub/symtab.h index e9a992c..742c205 --- a/symtab.h +++ b/FromGithub/symtab.h @@ -1,66 +1,66 @@ -/* $Id: symtab.h,v 1.5 2023/11/13 12:52:01 leavens Exp $ */ -#ifndef _SYMTAB_H -#define _SYMTAB_H - -#include "scope.h" -#include "id_use.h" - -// Maximum number of declarations that can be stored in a scope -#define MAX_NESTING 100 - -// initialize the symbol table -extern void symtab_initialize(); - -// Return the number of scopes currently in the symbol table. -extern unsigned int symtab_size(); - -// Does this symbol table have any scopes in it? -extern bool symtab_empty(); - -// Return the current scope's next location count -// (of constants and variables). -extern unsigned int symtab_scope_loc_count(); - -// Return the current scope's size (the number of declared ids). -extern unsigned int symtab_scope_size(); - -// Is the current scope full? -extern bool symtab_scope_full(); - -// Return the current nesting level of the symbol table -// (this is the number of symtab_enter_scope() calls -// minus the number of symtab_leave_scope() calls -extern unsigned int symtab_current_nesting_level(); - -// Is the symbol table itself full -// (i.e., is symtab_current_nesting_level() equal to MAX_NESTING-1)? -extern bool symtab_full(); - -// Is the given name associated with some attributes? -// (this looks back through all scopes). -extern bool symtab_defined(const char *name); - -// Is the given name associated with some attributes in the current scope? -// (this only looks in the current scope). -extern bool symtab_defined_in_current_scope(const char *name); - -// Requires: !symtab_defined_in_current_scope(name) && attrs != NULL -// Modify the current scope (as recorded in the symbol table) to -// add an association from the given name to the given attributes attrs. -extern void symtab_insert(const char *name, id_attrs *attrs); - -// Requires: !symtab_full() -// Start a new scope (for a procedure) -extern void symtab_enter_scope(); - -// Requires: !symtab_empty() -extern void symtab_leave_scope(); - -// Return (a pointer to) a struct containing: -// the attributes of the given name (attrs) -// and the number of lexical levels outward -// from the current scope at which the name was declared, -// or NULL if there is no association for name. -extern id_use *symtab_lookup(const char *name); - -#endif +/* $Id: symtab.h,v 1.5 2023/11/13 12:52:01 leavens Exp $ */ +#ifndef _SYMTAB_H +#define _SYMTAB_H + +#include "scope.h" +#include "id_use.h" + +// Maximum number of declarations that can be stored in a scope +#define MAX_NESTING 100 + +// initialize the symbol table +extern void symtab_initialize(); + +// Return the number of scopes currently in the symbol table. +extern unsigned int symtab_size(); + +// Does this symbol table have any scopes in it? +extern bool symtab_empty(); + +// Return the current scope's next location count +// (of constants and variables). +extern unsigned int symtab_scope_loc_count(); + +// Return the current scope's size (the number of declared ids). +extern unsigned int symtab_scope_size(); + +// Is the current scope full? +extern bool symtab_scope_full(); + +// Return the current nesting level of the symbol table +// (this is the number of symtab_enter_scope() calls +// minus the number of symtab_leave_scope() calls +extern unsigned int symtab_current_nesting_level(); + +// Is the symbol table itself full +// (i.e., is symtab_current_nesting_level() equal to MAX_NESTING-1)? +extern bool symtab_full(); + +// Is the given name associated with some attributes? +// (this looks back through all scopes). +extern bool symtab_defined(const char *name); + +// Is the given name associated with some attributes in the current scope? +// (this only looks in the current scope). +extern bool symtab_defined_in_current_scope(const char *name); + +// Requires: !symtab_defined_in_current_scope(name) && attrs != NULL +// Modify the current scope (as recorded in the symbol table) to +// add an association from the given name to the given attributes attrs. +extern void symtab_insert(const char *name, id_attrs *attrs); + +// Requires: !symtab_full() +// Start a new scope (for a procedure) +extern void symtab_enter_scope(); + +// Requires: !symtab_empty() +extern void symtab_leave_scope(); + +// Return (a pointer to) a struct containing: +// the attributes of the given name (attrs) +// and the number of lexical levels outward +// from the current scope at which the name was declared, +// or NULL if there is no association for name. +extern id_use *symtab_lookup(const char *name); + +#endif diff --git a/FromGithub/symtab.o b/FromGithub/symtab.o new file mode 100644 index 0000000..c71f8fa Binary files /dev/null and b/FromGithub/symtab.o differ diff --git a/unparser.c b/FromGithub/unparser.c old mode 100755 new mode 100644 similarity index 96% rename from unparser.c rename to FromGithub/unparser.c index 2db36db..4ad5b40 --- a/unparser.c +++ b/FromGithub/unparser.c @@ -1,427 +1,427 @@ -/* $Id: unparser.c,v 1.11 2024/10/23 13:38:20 leavens Exp $ */ -#include -#include -#include "unparser.h" -#include "utilities.h" - -// Amount of spaces to indent per nesting level -#define SPACES_PER_LEVEL 2 - -// Print SPACES_PER_LEVEL * level spaces to out -static void indent(FILE *out, int level) -{ - int num = SPACES_PER_LEVEL * level; - for (int i = 0; i < num; i++) { - fprintf(out, " "); - } -} - -// Print (to out) a semicolon, but only if addSemiToEnd is true, -// and then print a newline. -static void newlineAndOptionalSemi(FILE *out, bool addSemiToEnd) -{ - fprintf(out, "%s\n", (addSemiToEnd ? ";" : "")); -} - -// Unparse the given program AST and then print a period and an newline -void unparseProgram(FILE *out, block_t prog) -{ - unparseBlock(out, prog, 0, false); - fprintf(out, ".\n"); -} - -// Unparse the given block, indented by the given level, to out -// adding a semicolon to the end if addSemiToEnd is true. -extern void unparseBlock(FILE *out, block_t blk, int level, - bool addSemiToEnd) -{ - indent(out, level); - fprintf(out, "begin\n"); - unparseConstDecls(out, blk.const_decls, level+1); - unparseVarDecls(out, blk.var_decls, level+1); - unparseProcDecls(out, blk.proc_decls, level+1); - unparseStmts(out, blk.stmts, level+1); - indent(out, level); - fprintf(out, "end"); - newlineAndOptionalSemi(out, addSemiToEnd); -} - -// Unparse the list of const-decls given by the AST cds to out -// with the given nesting level -// (note that if cds == NULL, then nothing is printed) -void unparseConstDecls(FILE *out, const_decls_t cds, int level) -{ - // debug_print("unparseConstDecls entry ...\n"); - assert(cds.type_tag == const_decls_ast); - const_decl_t *cd_listp = cds.start; - while (cd_listp != NULL) { - unparseConstDecl(out, *cd_listp, level); - cd_listp = cd_listp->next; - } -} - -// Unparse a single const-def given by the AST cd to out, -// indented for the given nesting level -void unparseConstDecl(FILE *out, const_decl_t cd, int level) -{ - // debug_print("unparseConstDecl entry ...\n"); - indent(out, level); - fprintf(out, "const "); - unparseConstDefList(out, cd.const_def_list, level); -} - -// Unparse the list of const-defs given by the AST cdl to out -// with the given nesting level, followed by a semicolon and a newline. -void unparseConstDefList(FILE *out, const_def_list_t cdl, int level) -{ - // debug_print("unparseConstDefList entry ...\n"); - assert(cdl.type_tag == const_def_list_ast); - bool printed_already = false; - const_def_t *cdp = cdl.start; - while (cdp != NULL) { - if (printed_already) { - fprintf(out, ", "); - } - unparseConstDef(out, *cdp, level); - printed_already = true; - cdp = cdp->next; - } - fprintf(out, ";\n"); -} - -// Unparse the const-def given by the AST cdf to out -// with the given nesting level -extern void unparseConstDef(FILE *out, const_def_t cdf, int level) -{ - fprintf(out, "%s = %d", cdf.ident.name, cdf.number.value); -} - -// Unparse the list of vart-decls given by the AST vds to out -// with the given nesting level -// (note that if vds.var_decls == NULL, then nothing is printed) -void unparseVarDecls(FILE *out, var_decls_t vds, int level) -{ - // debug_print("Entering unparseVarDecls ...\n"); - assert(vds.type_tag == var_decls_ast); - var_decl_t *vdp = vds.var_decls; - while (vdp != NULL) { - unparseVarDecl(out, *vdp, level); - vdp = vdp->next; - } -} - -// Unparse a single var-decl given by the AST vd to out, -// indented for the given nesting level -void unparseVarDecl(FILE *out, var_decl_t vd, int level) -{ - // debug_print("Entering unparseVarDecl ...\n"); - indent(out, level); - fprintf(out, "var"); - unparseIdentList(out, vd.ident_list); - fprintf(out, ";\n"); -} - -// Unparse the identifiers in idents to out, with a space before each, -// and a comma as a separator -void unparseIdentList(FILE *out, ident_list_t ident_list) -{ - // debug_print("Entering unparseIdentList ...\n"); - ident_t *ip = ident_list.start; - bool already_printed =false; - while (ip != NULL) { - // debug_print("in unparseIdents ip is %x\n", ip); - // debug_print("in unparseIdents ip->name is %s\n", ip->name); - if (already_printed) { - fprintf(out, ", %s", ip->name); - } else { - fprintf(out, " %s", ip->name); - } - already_printed = true; - ip = ip->next; - } -} - -// Unparse the list of proc-decls given by the AST pds to out -// with the given nesting level -// (note that if pds.proc_decls is NULL, then nothing is printed) -void unparseProcDecls(FILE *out, proc_decls_t pds, int level) -{ - // debug_print("unparseProcDecls entry ...\n"); - assert(pds.type_tag == proc_decls_ast); - proc_decl_t *pdp = pds.proc_decls; - while (pdp != NULL) { - unparseProcDecl(out, *pdp, level); - pdp = pdp ->next; - } -} - -// Unparse the given proc-decl given by the AST pd to out -// with the given nesting level followed by a semicolon -void unparseProcDecl(FILE *out, proc_decl_t pd, int level) -{ - // debug_print("unparseProcDecl entry ...\n"); - indent(out, level); - fprintf(out, "proc %s\n", pd.name); - unparseBlock(out, *(pd.block), level, true); -} - - -// Unparse the stmts given by stmt to out -// with indentation level given by level. -// (The statements always occur before an end, so a semicolon is never added.) -void unparseStmts(FILE *out, stmts_t stmts, int level) -{ - // indent(out, level); - // fprintf(out, "%% stmts at level %d\n", level); - if (stmts.stmts_kind != empty_stmts_e) { - stmt_list_t sl = stmts.stmt_list; - unparseStmtList(out, sl, level, false); - } -} - -// Unparse the stmts given by stmt to out -// with indentation level given by level, -// and add a semicolon at the end if addSemiToEnd is true. -void unparseStmtList(FILE *out, stmt_list_t stmt_list, int level, - bool addSemiToEnd) -{ - // indent(out, level); - // fprintf(out, "%% stmtList at level %d\n", level); - stmt_t *s = stmt_list.start; - while (s != NULL) { - unparseStmt(out, *s, level, addSemiToEnd || (s->next != NULL)); - s = s->next; - } -} - -// Unparse the statement given by the AST stmt to out, -// indented for the given level, -// adding a semicolon to the end if addSemiToENd is true. -void unparseStmt(FILE *out, stmt_t stmt, int level, bool addSemiToEnd) -{ - // debug_print("In unparseStmt stmt.type_tag is %d\n", stmt.type_tag); - assert(stmt.type_tag == stmt_ast); - switch (stmt.stmt_kind) { - case assign_stmt: - assert(stmt.data.assign_stmt.type_tag == assign_stmt_ast); - unparseAssignStmt(out, stmt.data.assign_stmt, level, addSemiToEnd); - break; - case call_stmt: - unparseCallStmt(out, stmt.data.call_stmt, level, addSemiToEnd); - break; - case if_stmt: - unparseIfStmt(out, stmt.data.if_stmt, level, addSemiToEnd); - break; - case while_stmt: - unparseWhileStmt(out, stmt.data.while_stmt, level, addSemiToEnd); - break; - case read_stmt: - unparseReadStmt(out, stmt.data.read_stmt, level, addSemiToEnd); - break; - case print_stmt: - unparsePrintStmt(out, stmt.data.print_stmt, level, addSemiToEnd); - break; - case block_stmt: - unparseBlockStmt(out, stmt.data.block_stmt, level, addSemiToEnd); - break; - default: - bail_with_error("Unknown stmt_kind (%d) in unparseStmt!", - stmt.stmt_kind); - break; - } -} - -// Unparse the assignment statment given by stmt to out -// with indentation level given by level, -// and add a semicolon at the end if addSemiToEnd is true. -void unparseAssignStmt(FILE *out, assign_stmt_t stmt, int level, - bool addSemiToEnd) -{ - indent(out, level); - fprintf(out, "%s := ", stmt.name); - if (stmt.expr == NULL) { - bail_with_error("Found null expression in assignment statment!"); - } - unparseExpr(out, *(stmt.expr)); - newlineAndOptionalSemi(out, addSemiToEnd); -} - -// Unparse the call statment given by stmt to out -// with indentation level given by level, -// and add a semicolon at the end if addSemiToEnd is true. -void unparseCallStmt(FILE *out, call_stmt_t stmt, int level, - bool addSemiToEnd) -{ - indent(out, level); - fprintf(out, "call %s", stmt.name); - newlineAndOptionalSemi(out, addSemiToEnd); -} - -// Unparse the sequential statment given by stmt to out -// with indentation level given by level (indenting the body one more level) -// and add a semicolon at the end if addSemiToEnd is true. -void unparseBlockStmt(FILE *out, block_stmt_t stmt, int level, - bool addSemiToEnd) -{ - unparseBlock(out, *(stmt.block), level, addSemiToEnd); -} - -// Unparse the if-statment given by stmt to out -// with indentation level given by level (and each body indented one more), -// and add a semicolon at the end if addSemiToEnd is true. -void unparseIfStmt(FILE *out, if_stmt_t stmt, int level, bool addSemiToEnd) -{ - indent(out, level); - fprintf(out, "if "); - unparseCondition(out, stmt.condition); - fprintf(out, "\n"); - indent(out, level); - fprintf(out, "then\n"); - unparseStmts(out, *(stmt.then_stmts), level+1); - if (stmt.else_stmts != NULL) { - indent(out, level); - fprintf(out, "else\n"); - unparseStmts(out, *(stmt.else_stmts), level+1); - } - indent(out, level); - fprintf(out, "end"); - newlineAndOptionalSemi(out, addSemiToEnd); -} - -// Unparse the while-statment given by stmt to out -// with indentation level given by level (and the body indented one more), -// and add a semicolon at the end if addSemiToEnd is true. -void unparseWhileStmt(FILE *out, while_stmt_t stmt, int level, - bool addSemiToEnd) -{ - indent(out, level); - fprintf(out, "while "); - unparseCondition(out, stmt.condition); - fprintf(out, "\n"); - indent(out, level); - fprintf(out, "do\n"); - unparseStmts(out, *(stmt.body), level+1); - indent(out, level); - fprintf(out, "end"); - newlineAndOptionalSemi(out, addSemiToEnd); -} - -// Unparse the read statment given by stmt to out -// and add a semicolon at the end if addSemiToEnd is true. -void unparseReadStmt(FILE *out, read_stmt_t stmt, int level, bool addSemiToEnd) -{ - indent(out, level); - fprintf(out, "read %s", stmt.name); - newlineAndOptionalSemi(out, addSemiToEnd); -} - -// Unparse the write statment given by stmt to out -// and add a semicolon at the end if addSemiToEnd is true. -void unparsePrintStmt(FILE *out, print_stmt_t stmt, int level, - bool addSemiToEnd) -{ - indent(out, level); - fprintf(out, "print "); - unparseExpr(out, stmt.expr); - newlineAndOptionalSemi(out, addSemiToEnd); -} - -// Unparse the condition given by cond to out -void unparseCondition(FILE *out, condition_t cond) -{ - switch (cond.cond_kind) { - case ck_db: - unparseDbCond(out, cond.data.db_cond); - break; - case ck_rel: - unparseRelOpCond(out, cond.data.rel_op_cond); - break; - default: - bail_with_error("Unexpected condition_kind_e (%d) in unparseCondition!", - cond.cond_kind); - break; - } -} - -// Unparse the odd condition given by cond to out -void unparseDbCond(FILE *out, db_condition_t dbcond) -{ - fprintf(out, "divisible "); - unparseExpr(out, dbcond.dividend); - fprintf(out, " by "); - unparseExpr(out, dbcond.divisor); -} - -// Unparse the binary relation condition given by cond to out -void unparseRelOpCond(FILE *out, rel_op_condition_t cond) -{ - unparseExpr(out, cond.expr1); - fprintf(out, " "); - unparseToken(out, cond.rel_op); - fprintf(out, " "); - unparseExpr(out, cond.expr2); -} - -// Unparse the given token, t, to out -void unparseToken(FILE *out, token_t t) -{ - fprintf(out, "%s", t.text); -} - -// Unparse the expression given by the AST exp to out -// adding parentheses to indicate the nesting relationships -void unparseExpr(FILE *out, expr_t exp) -{ - switch (exp.expr_kind) { - case expr_bin: - unparseBinOpExpr(out, exp.data.binary); - break; - case expr_negated: - unparseNegatedExpr(out, exp.data.negated); - break; - case expr_ident: - unparseIdent(out, exp.data.ident); - break; - case expr_number: - unparseNumber(out, exp.data.number); - break; - default: - bail_with_error("Unexpected expr_kind_e (%d) in unparseExpr!", - exp.expr_kind); - break; - } -} - -// Unparse the expression given by the AST exp to out -// adding parentheses (whether needed or not) -void unparseBinOpExpr(FILE *out, binary_op_expr_t exp) -{ - fprintf(out, "("); - unparseExpr(out, *(exp.expr1)); - fprintf(out, " "); - unparseToken(out, exp.arith_op); - fprintf(out, " "); - unparseExpr(out, *(exp.expr2)); - fprintf(out, ")"); -} - -// Unparse the expression given by the AST exp to out -// adding parentheses (whether needed or not) -void unparseNegatedExpr(FILE *out, negated_expr_t exp) -{ - fprintf(out, "-("); - unparseExpr(out, *(exp.expr)); - fprintf(out, ")"); -} - -// Unparse the given identifier reference (i.e., identifier use), id, to out -void unparseIdent(FILE *out, ident_t id) -{ - fprintf(out, "%s", id.name); -} - -// Unparse the given number AST, num, to out in decimal format -void unparseNumber(FILE *out, number_t num) -{ - fprintf(out, "%d", num.value); -} +/* $Id: unparser.c,v 1.11 2024/10/23 13:38:20 leavens Exp $ */ +#include +#include +#include "unparser.h" +#include "utilities.h" + +// Amount of spaces to indent per nesting level +#define SPACES_PER_LEVEL 2 + +// Print SPACES_PER_LEVEL * level spaces to out +static void indent(FILE *out, int level) +{ + int num = SPACES_PER_LEVEL * level; + for (int i = 0; i < num; i++) { + fprintf(out, " "); + } +} + +// Print (to out) a semicolon, but only if addSemiToEnd is true, +// and then print a newline. +static void newlineAndOptionalSemi(FILE *out, bool addSemiToEnd) +{ + fprintf(out, "%s\n", (addSemiToEnd ? ";" : "")); +} + +// Unparse the given program AST and then print a period and an newline +void unparseProgram(FILE *out, block_t prog) +{ + unparseBlock(out, prog, 0, false); + fprintf(out, ".\n"); +} + +// Unparse the given block, indented by the given level, to out +// adding a semicolon to the end if addSemiToEnd is true. +extern void unparseBlock(FILE *out, block_t blk, int level, + bool addSemiToEnd) +{ + indent(out, level); + fprintf(out, "begin\n"); + unparseConstDecls(out, blk.const_decls, level+1); + unparseVarDecls(out, blk.var_decls, level+1); + unparseProcDecls(out, blk.proc_decls, level+1); + unparseStmts(out, blk.stmts, level+1); + indent(out, level); + fprintf(out, "end"); + newlineAndOptionalSemi(out, addSemiToEnd); +} + +// Unparse the list of const-decls given by the AST cds to out +// with the given nesting level +// (note that if cds == NULL, then nothing is printed) +void unparseConstDecls(FILE *out, const_decls_t cds, int level) +{ + // debug_print("unparseConstDecls entry ...\n"); + assert(cds.type_tag == const_decls_ast); + const_decl_t *cd_listp = cds.start; + while (cd_listp != NULL) { + unparseConstDecl(out, *cd_listp, level); + cd_listp = cd_listp->next; + } +} + +// Unparse a single const-def given by the AST cd to out, +// indented for the given nesting level +void unparseConstDecl(FILE *out, const_decl_t cd, int level) +{ + // debug_print("unparseConstDecl entry ...\n"); + indent(out, level); + fprintf(out, "const "); + unparseConstDefList(out, cd.const_def_list, level); +} + +// Unparse the list of const-defs given by the AST cdl to out +// with the given nesting level, followed by a semicolon and a newline. +void unparseConstDefList(FILE *out, const_def_list_t cdl, int level) +{ + // debug_print("unparseConstDefList entry ...\n"); + assert(cdl.type_tag == const_def_list_ast); + bool printed_already = false; + const_def_t *cdp = cdl.start; + while (cdp != NULL) { + if (printed_already) { + fprintf(out, ", "); + } + unparseConstDef(out, *cdp, level); + printed_already = true; + cdp = cdp->next; + } + fprintf(out, ";\n"); +} + +// Unparse the const-def given by the AST cdf to out +// with the given nesting level +extern void unparseConstDef(FILE *out, const_def_t cdf, int level) +{ + fprintf(out, "%s = %d", cdf.ident.name, cdf.number.value); +} + +// Unparse the list of vart-decls given by the AST vds to out +// with the given nesting level +// (note that if vds.var_decls == NULL, then nothing is printed) +void unparseVarDecls(FILE *out, var_decls_t vds, int level) +{ + // debug_print("Entering unparseVarDecls ...\n"); + assert(vds.type_tag == var_decls_ast); + var_decl_t *vdp = vds.var_decls; + while (vdp != NULL) { + unparseVarDecl(out, *vdp, level); + vdp = vdp->next; + } +} + +// Unparse a single var-decl given by the AST vd to out, +// indented for the given nesting level +void unparseVarDecl(FILE *out, var_decl_t vd, int level) +{ + // debug_print("Entering unparseVarDecl ...\n"); + indent(out, level); + fprintf(out, "var"); + unparseIdentList(out, vd.ident_list); + fprintf(out, ";\n"); +} + +// Unparse the identifiers in idents to out, with a space before each, +// and a comma as a separator +void unparseIdentList(FILE *out, ident_list_t ident_list) +{ + // debug_print("Entering unparseIdentList ...\n"); + ident_t *ip = ident_list.start; + bool already_printed =false; + while (ip != NULL) { + // debug_print("in unparseIdents ip is %x\n", ip); + // debug_print("in unparseIdents ip->name is %s\n", ip->name); + if (already_printed) { + fprintf(out, ", %s", ip->name); + } else { + fprintf(out, " %s", ip->name); + } + already_printed = true; + ip = ip->next; + } +} + +// Unparse the list of proc-decls given by the AST pds to out +// with the given nesting level +// (note that if pds.proc_decls is NULL, then nothing is printed) +void unparseProcDecls(FILE *out, proc_decls_t pds, int level) +{ + // debug_print("unparseProcDecls entry ...\n"); + assert(pds.type_tag == proc_decls_ast); + proc_decl_t *pdp = pds.proc_decls; + while (pdp != NULL) { + unparseProcDecl(out, *pdp, level); + pdp = pdp ->next; + } +} + +// Unparse the given proc-decl given by the AST pd to out +// with the given nesting level followed by a semicolon +void unparseProcDecl(FILE *out, proc_decl_t pd, int level) +{ + // debug_print("unparseProcDecl entry ...\n"); + indent(out, level); + fprintf(out, "proc %s\n", pd.name); + unparseBlock(out, *(pd.block), level, true); +} + + +// Unparse the stmts given by stmt to out +// with indentation level given by level. +// (The statements always occur before an end, so a semicolon is never added.) +void unparseStmts(FILE *out, stmts_t stmts, int level) +{ + // indent(out, level); + // fprintf(out, "%% stmts at level %d\n", level); + if (stmts.stmts_kind != empty_stmts_e) { + stmt_list_t sl = stmts.stmt_list; + unparseStmtList(out, sl, level, false); + } +} + +// Unparse the stmts given by stmt to out +// with indentation level given by level, +// and add a semicolon at the end if addSemiToEnd is true. +void unparseStmtList(FILE *out, stmt_list_t stmt_list, int level, + bool addSemiToEnd) +{ + // indent(out, level); + // fprintf(out, "%% stmtList at level %d\n", level); + stmt_t *s = stmt_list.start; + while (s != NULL) { + unparseStmt(out, *s, level, addSemiToEnd || (s->next != NULL)); + s = s->next; + } +} + +// Unparse the statement given by the AST stmt to out, +// indented for the given level, +// adding a semicolon to the end if addSemiToENd is true. +void unparseStmt(FILE *out, stmt_t stmt, int level, bool addSemiToEnd) +{ + // debug_print("In unparseStmt stmt.type_tag is %d\n", stmt.type_tag); + assert(stmt.type_tag == stmt_ast); + switch (stmt.stmt_kind) { + case assign_stmt: + assert(stmt.data.assign_stmt.type_tag == assign_stmt_ast); + unparseAssignStmt(out, stmt.data.assign_stmt, level, addSemiToEnd); + break; + case call_stmt: + unparseCallStmt(out, stmt.data.call_stmt, level, addSemiToEnd); + break; + case if_stmt: + unparseIfStmt(out, stmt.data.if_stmt, level, addSemiToEnd); + break; + case while_stmt: + unparseWhileStmt(out, stmt.data.while_stmt, level, addSemiToEnd); + break; + case read_stmt: + unparseReadStmt(out, stmt.data.read_stmt, level, addSemiToEnd); + break; + case print_stmt: + unparsePrintStmt(out, stmt.data.print_stmt, level, addSemiToEnd); + break; + case block_stmt: + unparseBlockStmt(out, stmt.data.block_stmt, level, addSemiToEnd); + break; + default: + bail_with_error("Unknown stmt_kind (%d) in unparseStmt!", + stmt.stmt_kind); + break; + } +} + +// Unparse the assignment statment given by stmt to out +// with indentation level given by level, +// and add a semicolon at the end if addSemiToEnd is true. +void unparseAssignStmt(FILE *out, assign_stmt_t stmt, int level, + bool addSemiToEnd) +{ + indent(out, level); + fprintf(out, "%s := ", stmt.name); + if (stmt.expr == NULL) { + bail_with_error("Found null expression in assignment statment!"); + } + unparseExpr(out, *(stmt.expr)); + newlineAndOptionalSemi(out, addSemiToEnd); +} + +// Unparse the call statment given by stmt to out +// with indentation level given by level, +// and add a semicolon at the end if addSemiToEnd is true. +void unparseCallStmt(FILE *out, call_stmt_t stmt, int level, + bool addSemiToEnd) +{ + indent(out, level); + fprintf(out, "call %s", stmt.name); + newlineAndOptionalSemi(out, addSemiToEnd); +} + +// Unparse the sequential statment given by stmt to out +// with indentation level given by level (indenting the body one more level) +// and add a semicolon at the end if addSemiToEnd is true. +void unparseBlockStmt(FILE *out, block_stmt_t stmt, int level, + bool addSemiToEnd) +{ + unparseBlock(out, *(stmt.block), level, addSemiToEnd); +} + +// Unparse the if-statment given by stmt to out +// with indentation level given by level (and each body indented one more), +// and add a semicolon at the end if addSemiToEnd is true. +void unparseIfStmt(FILE *out, if_stmt_t stmt, int level, bool addSemiToEnd) +{ + indent(out, level); + fprintf(out, "if "); + unparseCondition(out, stmt.condition); + fprintf(out, "\n"); + indent(out, level); + fprintf(out, "then\n"); + unparseStmts(out, *(stmt.then_stmts), level+1); + if (stmt.else_stmts != NULL) { + indent(out, level); + fprintf(out, "else\n"); + unparseStmts(out, *(stmt.else_stmts), level+1); + } + indent(out, level); + fprintf(out, "end"); + newlineAndOptionalSemi(out, addSemiToEnd); +} + +// Unparse the while-statment given by stmt to out +// with indentation level given by level (and the body indented one more), +// and add a semicolon at the end if addSemiToEnd is true. +void unparseWhileStmt(FILE *out, while_stmt_t stmt, int level, + bool addSemiToEnd) +{ + indent(out, level); + fprintf(out, "while "); + unparseCondition(out, stmt.condition); + fprintf(out, "\n"); + indent(out, level); + fprintf(out, "do\n"); + unparseStmts(out, *(stmt.body), level+1); + indent(out, level); + fprintf(out, "end"); + newlineAndOptionalSemi(out, addSemiToEnd); +} + +// Unparse the read statment given by stmt to out +// and add a semicolon at the end if addSemiToEnd is true. +void unparseReadStmt(FILE *out, read_stmt_t stmt, int level, bool addSemiToEnd) +{ + indent(out, level); + fprintf(out, "read %s", stmt.name); + newlineAndOptionalSemi(out, addSemiToEnd); +} + +// Unparse the write statment given by stmt to out +// and add a semicolon at the end if addSemiToEnd is true. +void unparsePrintStmt(FILE *out, print_stmt_t stmt, int level, + bool addSemiToEnd) +{ + indent(out, level); + fprintf(out, "print "); + unparseExpr(out, stmt.expr); + newlineAndOptionalSemi(out, addSemiToEnd); +} + +// Unparse the condition given by cond to out +void unparseCondition(FILE *out, condition_t cond) +{ + switch (cond.cond_kind) { + case ck_db: + unparseDbCond(out, cond.data.db_cond); + break; + case ck_rel: + unparseRelOpCond(out, cond.data.rel_op_cond); + break; + default: + bail_with_error("Unexpected condition_kind_e (%d) in unparseCondition!", + cond.cond_kind); + break; + } +} + +// Unparse the odd condition given by cond to out +void unparseDbCond(FILE *out, db_condition_t dbcond) +{ + fprintf(out, "divisible "); + unparseExpr(out, dbcond.dividend); + fprintf(out, " by "); + unparseExpr(out, dbcond.divisor); +} + +// Unparse the binary relation condition given by cond to out +void unparseRelOpCond(FILE *out, rel_op_condition_t cond) +{ + unparseExpr(out, cond.expr1); + fprintf(out, " "); + unparseToken(out, cond.rel_op); + fprintf(out, " "); + unparseExpr(out, cond.expr2); +} + +// Unparse the given token, t, to out +void unparseToken(FILE *out, token_t t) +{ + fprintf(out, "%s", t.text); +} + +// Unparse the expression given by the AST exp to out +// adding parentheses to indicate the nesting relationships +void unparseExpr(FILE *out, expr_t exp) +{ + switch (exp.expr_kind) { + case expr_bin: + unparseBinOpExpr(out, exp.data.binary); + break; + case expr_negated: + unparseNegatedExpr(out, exp.data.negated); + break; + case expr_ident: + unparseIdent(out, exp.data.ident); + break; + case expr_number: + unparseNumber(out, exp.data.number); + break; + default: + bail_with_error("Unexpected expr_kind_e (%d) in unparseExpr!", + exp.expr_kind); + break; + } +} + +// Unparse the expression given by the AST exp to out +// adding parentheses (whether needed or not) +void unparseBinOpExpr(FILE *out, binary_op_expr_t exp) +{ + fprintf(out, "("); + unparseExpr(out, *(exp.expr1)); + fprintf(out, " "); + unparseToken(out, exp.arith_op); + fprintf(out, " "); + unparseExpr(out, *(exp.expr2)); + fprintf(out, ")"); +} + +// Unparse the expression given by the AST exp to out +// adding parentheses (whether needed or not) +void unparseNegatedExpr(FILE *out, negated_expr_t exp) +{ + fprintf(out, "-("); + unparseExpr(out, *(exp.expr)); + fprintf(out, ")"); +} + +// Unparse the given identifier reference (i.e., identifier use), id, to out +void unparseIdent(FILE *out, ident_t id) +{ + fprintf(out, "%s", id.name); +} + +// Unparse the given number AST, num, to out in decimal format +void unparseNumber(FILE *out, number_t num) +{ + fprintf(out, "%d", num.value); +} diff --git a/unparser.h b/FromGithub/unparser.h old mode 100755 new mode 100644 similarity index 97% rename from unparser.h rename to FromGithub/unparser.h index 04ec623..b3e65b0 --- a/unparser.h +++ b/FromGithub/unparser.h @@ -1,138 +1,138 @@ -/* $Id: unparser.h,v 1.6 2024/10/23 14:55:24 leavens Exp $ */ -#ifndef _UNPARSER_H -#define _UNPARSER_H -#include -#include "ast.h" - -// Unparse the given program AST and then print a period and an newline -extern void unparseProgram(FILE *out, block_t prog); - -// Unparse the given block, indented by the given level, to out -// adding a semicolon to the end if addSemiToEnd is true. -extern void unparseBlock(FILE *out, block_t blk, int indentLevel, - bool addSemiToEnd); - -// Unparse the list of const-decls given by the AST cds to out -// with the given nesting level -// (note that if cds is empty, then nothing is printed) -extern void unparseConstDecls(FILE *out, const_decls_t cds, int level); - -// Unparse the const-decl given by the AST cd to out -// with the given nesting level -extern void unparseConstDecl(FILE *out, const_decl_t cd, int level); - -// Unparse the list of const-defs given by the AST cdl to out -// with the given nesting level -extern void unparseConstDefList(FILE *out, const_def_list_t cdl, int level); - -// Unparse the const-def given by the AST cdf to out -// with the given nesting level -extern void unparseConstDef(FILE *out, const_def_t cdf, int level); - -// Unparse the list of var-decls given by the AST vds to out -// with the given nesting level -// (note that if vds.var_decls == NULL, then nothing is printed) -extern void unparseVarDecls(FILE *out, var_decls_t vds, int level); - -// Unparse the var-decl given by the AST vd to out -// with the given nesting level -extern void unparseVarDecl(FILE *out, var_decl_t vd, int level); - -// Unparse the identifiers in idents to out, with a space before each, -// and a comma as a separator -extern void unparseIdentList(FILE *out, ident_list_t ident_list); - -// Unparse the list of proc-decls given by the AST pds to out -// with the given nesting level -// (note that if pds.proc_decls is NULL, then nothing is printed) -extern void unparseProcDecls(FILE *out, proc_decls_t pds, int level); - -// Unparse the given proc-decl given by the AST pd to out -// with the given nesting level -extern void unparseProcDecl(FILE *out, proc_decl_t pd, int level); - -// Unparse the statement given by the AST stmt to out, -// indented for the given level, -// adding a semicolon to the end if addSemiToEnd is true. -extern void unparseStmt(FILE *out, stmt_t stmt, int indentLevel, - bool addSemiToEnd); - -// Unparse the statement given by the AST stmt to out, -// indented for the given level, -// adding a semicolon to the end if addSemiToEnd is true. -extern void unparseAssignStmt(FILE *out, assign_stmt_t stmt, int level, bool addSemiToEnd); - -// Unparse the statement given by the AST stmt to out, -// indented for the given level, -// adding a semicolon to the end if addSemiToEnd is true. -extern void unparseCallStmt(FILE *out, call_stmt_t stmt, int level, bool addSemiToEnd); - -// Unparse the statement given by the AST stmt to out, -// indented for the given level, -// adding a semicolon to the end if addSemiToEnd is true. -extern void unparseBlockStmt(FILE *out, block_stmt_t stmt, int level, bool addSemiToEnd); - -// Unparse the statements given by the AST stmts to out, -// indented for the given level. -// (The statements always occur before an end, so a semicolon is never added.) -extern void unparseStmts(FILE *out, stmts_t stmts, int level); - -// Unparse the stmts given by stmt to out -// with indentation level given by level, -// and add a semicolon at the end if addSemiToEnd is true. -void unparseStmtList(FILE *out, stmt_list_t stmt_list, int level, - bool addSemiToEnd); - -// Unparse the statement given by the AST stmt to out, -// indented for the given level, -// adding a semicolon to the end if addSemiToEnd is true. -extern void unparseIfStmt(FILE *out, if_stmt_t stmt, int level, - bool addSemiToEnd); - -// Unparse the statement given by the AST stmt to out, -// indented for the given level, -// adding a semicolon to the end if addSemiToEnd is true. -extern void unparseWhileStmt(FILE *out, while_stmt_t stmt, int level, - bool addSemiToEnd); - -// Unparse the statement given by the AST stmt to out, -// indented for the given level, -// adding a semicolon to the end if addSemiToEnd is true. -extern void unparseReadStmt(FILE *out, read_stmt_t stmt, int level, - bool addSemiToEnd); - -// Unparse the statement given by the AST stmt to out, -// indented for the given level, -// adding a semicolon to the end if addSemiToEnd is true. -extern void unparsePrintStmt(FILE *out, print_stmt_t stmt, int level, bool addSemiToEnd); - -// Unparse the condition given by cond to out -extern void unparseCondition(FILE *out, condition_t cond); - -extern void unparseDbCond(FILE *out, db_condition_t cond); - -extern void unparseRelOpCond(FILE *out, rel_op_condition_t cond); - -// Unparse the given token, t, to out -extern void unparseToken(FILE *out, token_t t); - -// Unparse the expression given by the AST exp to out -// adding parentheses to indicate the nesting relationships -extern void unparseExpr(FILE *out, expr_t exp); - -extern void unparseBinOpExpr(FILE *out, binary_op_expr_t exp); - -// Unparse the given bin_arith_opo to out -extern void unparseArithOp(FILE *out, token_t arith_op); - -// Unparse the expression given by the AST exp to out -// adding parentheses (whether needed or not) -extern void unparseNegatedExpr(FILE *out, negated_expr_t exp); - -// Unparse the given identifer reference (use) to out -extern void unparseIdent(FILE *out, ident_t id); - -// Unparse the given number to out in decimal format -extern void unparseNumber(FILE *out, number_t num); - -#endif +/* $Id: unparser.h,v 1.6 2024/10/23 14:55:24 leavens Exp $ */ +#ifndef _UNPARSER_H +#define _UNPARSER_H +#include +#include "ast.h" + +// Unparse the given program AST and then print a period and an newline +extern void unparseProgram(FILE *out, block_t prog); + +// Unparse the given block, indented by the given level, to out +// adding a semicolon to the end if addSemiToEnd is true. +extern void unparseBlock(FILE *out, block_t blk, int indentLevel, + bool addSemiToEnd); + +// Unparse the list of const-decls given by the AST cds to out +// with the given nesting level +// (note that if cds is empty, then nothing is printed) +extern void unparseConstDecls(FILE *out, const_decls_t cds, int level); + +// Unparse the const-decl given by the AST cd to out +// with the given nesting level +extern void unparseConstDecl(FILE *out, const_decl_t cd, int level); + +// Unparse the list of const-defs given by the AST cdl to out +// with the given nesting level +extern void unparseConstDefList(FILE *out, const_def_list_t cdl, int level); + +// Unparse the const-def given by the AST cdf to out +// with the given nesting level +extern void unparseConstDef(FILE *out, const_def_t cdf, int level); + +// Unparse the list of var-decls given by the AST vds to out +// with the given nesting level +// (note that if vds.var_decls == NULL, then nothing is printed) +extern void unparseVarDecls(FILE *out, var_decls_t vds, int level); + +// Unparse the var-decl given by the AST vd to out +// with the given nesting level +extern void unparseVarDecl(FILE *out, var_decl_t vd, int level); + +// Unparse the identifiers in idents to out, with a space before each, +// and a comma as a separator +extern void unparseIdentList(FILE *out, ident_list_t ident_list); + +// Unparse the list of proc-decls given by the AST pds to out +// with the given nesting level +// (note that if pds.proc_decls is NULL, then nothing is printed) +extern void unparseProcDecls(FILE *out, proc_decls_t pds, int level); + +// Unparse the given proc-decl given by the AST pd to out +// with the given nesting level +extern void unparseProcDecl(FILE *out, proc_decl_t pd, int level); + +// Unparse the statement given by the AST stmt to out, +// indented for the given level, +// adding a semicolon to the end if addSemiToEnd is true. +extern void unparseStmt(FILE *out, stmt_t stmt, int indentLevel, + bool addSemiToEnd); + +// Unparse the statement given by the AST stmt to out, +// indented for the given level, +// adding a semicolon to the end if addSemiToEnd is true. +extern void unparseAssignStmt(FILE *out, assign_stmt_t stmt, int level, bool addSemiToEnd); + +// Unparse the statement given by the AST stmt to out, +// indented for the given level, +// adding a semicolon to the end if addSemiToEnd is true. +extern void unparseCallStmt(FILE *out, call_stmt_t stmt, int level, bool addSemiToEnd); + +// Unparse the statement given by the AST stmt to out, +// indented for the given level, +// adding a semicolon to the end if addSemiToEnd is true. +extern void unparseBlockStmt(FILE *out, block_stmt_t stmt, int level, bool addSemiToEnd); + +// Unparse the statements given by the AST stmts to out, +// indented for the given level. +// (The statements always occur before an end, so a semicolon is never added.) +extern void unparseStmts(FILE *out, stmts_t stmts, int level); + +// Unparse the stmts given by stmt to out +// with indentation level given by level, +// and add a semicolon at the end if addSemiToEnd is true. +void unparseStmtList(FILE *out, stmt_list_t stmt_list, int level, + bool addSemiToEnd); + +// Unparse the statement given by the AST stmt to out, +// indented for the given level, +// adding a semicolon to the end if addSemiToEnd is true. +extern void unparseIfStmt(FILE *out, if_stmt_t stmt, int level, + bool addSemiToEnd); + +// Unparse the statement given by the AST stmt to out, +// indented for the given level, +// adding a semicolon to the end if addSemiToEnd is true. +extern void unparseWhileStmt(FILE *out, while_stmt_t stmt, int level, + bool addSemiToEnd); + +// Unparse the statement given by the AST stmt to out, +// indented for the given level, +// adding a semicolon to the end if addSemiToEnd is true. +extern void unparseReadStmt(FILE *out, read_stmt_t stmt, int level, + bool addSemiToEnd); + +// Unparse the statement given by the AST stmt to out, +// indented for the given level, +// adding a semicolon to the end if addSemiToEnd is true. +extern void unparsePrintStmt(FILE *out, print_stmt_t stmt, int level, bool addSemiToEnd); + +// Unparse the condition given by cond to out +extern void unparseCondition(FILE *out, condition_t cond); + +extern void unparseDbCond(FILE *out, db_condition_t cond); + +extern void unparseRelOpCond(FILE *out, rel_op_condition_t cond); + +// Unparse the given token, t, to out +extern void unparseToken(FILE *out, token_t t); + +// Unparse the expression given by the AST exp to out +// adding parentheses to indicate the nesting relationships +extern void unparseExpr(FILE *out, expr_t exp); + +extern void unparseBinOpExpr(FILE *out, binary_op_expr_t exp); + +// Unparse the given bin_arith_opo to out +extern void unparseArithOp(FILE *out, token_t arith_op); + +// Unparse the expression given by the AST exp to out +// adding parentheses (whether needed or not) +extern void unparseNegatedExpr(FILE *out, negated_expr_t exp); + +// Unparse the given identifer reference (use) to out +extern void unparseIdent(FILE *out, ident_t id); + +// Unparse the given number to out in decimal format +extern void unparseNumber(FILE *out, number_t num); + +#endif diff --git a/FromGithub/unparser.o b/FromGithub/unparser.o new file mode 100644 index 0000000..1cf3aa1 Binary files /dev/null and b/FromGithub/unparser.o differ diff --git a/utilities.c b/FromGithub/utilities.c old mode 100755 new mode 100644 similarity index 96% rename from utilities.c rename to FromGithub/utilities.c index dc62a04..07ada71 --- a/utilities.c +++ b/FromGithub/utilities.c @@ -1,113 +1,113 @@ -/* $Id: utilities.c,v 1.4 2024/10/23 12:17:39 leavens Exp $ */ -#include -#include -#include -#include -#include -#include -#include "utilities.h" - -// to turn off debugging support (assertions and debug_print) -// define the symbol NDEBUG (by writing uncommenting the following) -// #define NDEBUG - -#ifdef NDEBUG -#define debug_print() ((void)0) -#else -// otherwise debugging is on, and debug_print is defined as follows... -// (note that assert is a macro defined in -static void vdebug_print(const char *fmt, va_list args); - -// If debugging is false, do nothing, otherwise (when debugging) -// flush stderr and stdout, then print the message given on stderr, -// using printf formatting from the format string fmt. -// This function returns normally. -void debug_print(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - vdebug_print(fmt, args); - va_end(args); -} - -// The variadic version of debug_print -static void vdebug_print(const char *fmt, va_list args) -{ - // flush output streams to synchronize outputs - fflush(stdout); - fflush(stderr); - vfprintf(stderr, fmt, args); - fflush(stderr); -} -#endif - -static void vbail_with_error(const char* fmt, va_list args); - -// Format a string error message and print it followed by a newline on stderr -// using perror (for an OS error, if the errno is not 0) -// then exit with a failure code, so a call to this does not return. -void bail_with_error(const char *fmt, ...) -{ - fflush(stdout); // flush so output comes after what has happened already - va_list(args); - va_start(args, fmt); - vbail_with_error(fmt, args); -} - -// The variadic version of bail_with_error -static void vbail_with_error(const char* fmt, va_list args) -{ - extern int errno; - char buff[2048]; - vsprintf(buff, fmt, args); - if (errno != 0) { - perror(buff); - } else { - fprintf(stderr, "%s\n", buff); - } - fflush(stderr); - exit(EXIT_FAILURE); -} - -// Print an error message on stderr -// starting with the file name and line number from the floc argument -// (prints: filename, a colon, " line ", the line number, and a space) -// and then the message. -// Then exit with a failure code, so this function does not return. -void bail_with_prog_error(file_location floc, const char *fmt, ...) -{ - fflush(stdout); // flush so output comes after what has happened already - // print file, line, column information - fprintf(stderr, "%s: line %d ", floc.filename, floc.line); - - va_list(args); - va_start(args, fmt); - vbail_with_error(fmt, args); -} - -#define BUF_SIZE 1024 - -// Call yyerror to print an error message on stderr -// starting with the filename, ":", the lexer's current line number, ": ", -// and then the formatted message (as in sprintf) -extern void formatted_yyerror(const char *filename, const char *fmt, ...) -{ - fflush(stdout); // flush so output comes after what has happened already - - char buf[BUF_SIZE]; - va_list(args); - va_start(args, fmt); - vsnprintf(buf, BUF_SIZE, fmt, args); - yyerror(filename, buf); - va_end(args); -} - - - -// print a newline on out and flush out -void newline(FILE *out) -{ - fprintf(out, "\n"); - fflush(out); -} - +/* $Id: utilities.c,v 1.4 2024/10/23 12:17:39 leavens Exp $ */ +#include +#include +#include +#include +#include +#include +#include "utilities.h" + +// to turn off debugging support (assertions and debug_print) +// define the symbol NDEBUG (by writing uncommenting the following) +// #define NDEBUG + +#ifdef NDEBUG +#define debug_print() ((void)0) +#else +// otherwise debugging is on, and debug_print is defined as follows... +// (note that assert is a macro defined in +static void vdebug_print(const char *fmt, va_list args); + +// If debugging is false, do nothing, otherwise (when debugging) +// flush stderr and stdout, then print the message given on stderr, +// using printf formatting from the format string fmt. +// This function returns normally. +void debug_print(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vdebug_print(fmt, args); + va_end(args); +} + +// The variadic version of debug_print +static void vdebug_print(const char *fmt, va_list args) +{ + // flush output streams to synchronize outputs + fflush(stdout); + fflush(stderr); + vfprintf(stderr, fmt, args); + fflush(stderr); +} +#endif + +static void vbail_with_error(const char* fmt, va_list args); + +// Format a string error message and print it followed by a newline on stderr +// using perror (for an OS error, if the errno is not 0) +// then exit with a failure code, so a call to this does not return. +void bail_with_error(const char *fmt, ...) +{ + fflush(stdout); // flush so output comes after what has happened already + va_list(args); + va_start(args, fmt); + vbail_with_error(fmt, args); +} + +// The variadic version of bail_with_error +static void vbail_with_error(const char* fmt, va_list args) +{ + extern int errno; + char buff[2048]; + vsprintf(buff, fmt, args); + if (errno != 0) { + perror(buff); + } else { + fprintf(stderr, "%s\n", buff); + } + fflush(stderr); + exit(EXIT_FAILURE); +} + +// Print an error message on stderr +// starting with the file name and line number from the floc argument +// (prints: filename, a colon, " line ", the line number, and a space) +// and then the message. +// Then exit with a failure code, so this function does not return. +void bail_with_prog_error(file_location floc, const char *fmt, ...) +{ + fflush(stdout); // flush so output comes after what has happened already + // print file, line, column information + fprintf(stderr, "%s: line %d ", floc.filename, floc.line); + + va_list(args); + va_start(args, fmt); + vbail_with_error(fmt, args); +} + +#define BUF_SIZE 1024 + +// Call yyerror to print an error message on stderr +// starting with the filename, ":", the lexer's current line number, ": ", +// and then the formatted message (as in sprintf) +extern void formatted_yyerror(const char *filename, const char *fmt, ...) +{ + fflush(stdout); // flush so output comes after what has happened already + + char buf[BUF_SIZE]; + va_list(args); + va_start(args, fmt); + vsnprintf(buf, BUF_SIZE, fmt, args); + yyerror(filename, buf); + va_end(args); +} + + + +// print a newline on out and flush out +void newline(FILE *out) +{ + fprintf(out, "\n"); + fflush(out); +} + diff --git a/utilities.h b/FromGithub/utilities.h old mode 100755 new mode 100644 similarity index 97% rename from utilities.h rename to FromGithub/utilities.h index 5549807..7a10aae --- a/utilities.h +++ b/FromGithub/utilities.h @@ -1,37 +1,37 @@ -/* $Id: utilities.h,v 1.5 2024/11/13 14:08:23 leavens Exp $ */ -#ifndef _UTILITIES_H -#define _UTILITIES_H -#include -#include -#include -#include "file_location.h" -#include "lexer_utilities.h" - -#define MAX(x,y) (((x)>(y))?(x):(y)) - -// If NDEBUG is defined, do nothing, otherwise (when debugging) -// flush stderr and stdout, then print the message given on stderr, -// using printf formatting from the format string fmt. -// This function returns normally. -void debug_print(const char *fmt, ...); - -// Format a string error message and print it using perror (for an OS error) -// then exit with a failure code, so a call to this does not return. -extern void bail_with_error(const char *fmt, ...); - -// Print an error message on stderr -// starting with the file name and line number from the floc argument -// (prints: filename, a colon, " line ", the line number, and a space) -// and then the message. -// Then exit with a failure code, so this function does not return. -extern void bail_with_prog_error(file_location floc, const char *fmt, ...); - -// Call yyerror to print an error message on stderr -// starting with the filename, ":", the lexer's current line number, ": ", -// and then the formatted message (as in sprintf) -extern void formatted_yyerror(const char *filename, const char *fmt, ...); - -// print a newline on out and flush out -extern void newline(FILE *out); - -#endif +/* $Id: utilities.h,v 1.5 2024/11/13 14:08:23 leavens Exp $ */ +#ifndef _UTILITIES_H +#define _UTILITIES_H +#include +#include +#include +#include "file_location.h" +#include "lexer_utilities.h" + +#define MAX(x,y) (((x)>(y))?(x):(y)) + +// If NDEBUG is defined, do nothing, otherwise (when debugging) +// flush stderr and stdout, then print the message given on stderr, +// using printf formatting from the format string fmt. +// This function returns normally. +void debug_print(const char *fmt, ...); + +// Format a string error message and print it using perror (for an OS error) +// then exit with a failure code, so a call to this does not return. +extern void bail_with_error(const char *fmt, ...); + +// Print an error message on stderr +// starting with the file name and line number from the floc argument +// (prints: filename, a colon, " line ", the line number, and a space) +// and then the message. +// Then exit with a failure code, so this function does not return. +extern void bail_with_prog_error(file_location floc, const char *fmt, ...); + +// Call yyerror to print an error message on stderr +// starting with the filename, ":", the lexer's current line number, ": ", +// and then the formatted message (as in sprintf) +extern void formatted_yyerror(const char *filename, const char *fmt, ...); + +// print a newline on out and flush out +extern void newline(FILE *out); + +#endif diff --git a/FromGithub/utilities.o b/FromGithub/utilities.o new file mode 100644 index 0000000..a0954e2 Binary files /dev/null and b/FromGithub/utilities.o differ diff --git a/Group_Member_Responsibility_Certification.docx b/Group_Member_Responsibility_Certification.docx deleted file mode 100644 index 3d12bba..0000000 Binary files a/Group_Member_Responsibility_Certification.docx and /dev/null differ diff --git a/hw4-code-generation.pdf b/hw4-code-generation.pdf deleted file mode 100644 index 45d9963..0000000 Binary files a/hw4-code-generation.pdf and /dev/null differ diff --git a/hw4-tests.zip b/hw4-tests.zip deleted file mode 100644 index fc1bbcb..0000000 Binary files a/hw4-tests.zip and /dev/null differ diff --git a/spl-manual.pdf b/spl-manual.pdf deleted file mode 100644 index 0cd7ee5..0000000 Binary files a/spl-manual.pdf and /dev/null differ diff --git a/vm/BOF_layout.png b/vm/BOF_layout.png deleted file mode 100755 index b8ef9b2..0000000 Binary files a/vm/BOF_layout.png and /dev/null differ diff --git a/vm/Makefile b/vm/Makefile deleted file mode 100755 index e5f08bd..0000000 --- a/vm/Makefile +++ /dev/null @@ -1,165 +0,0 @@ -# $Id: Makefile,v 1.72 2024/11/13 15:36:59 leavens Exp leavens $ - -# Add .exe to the end of target to get that suffix in the rules -VM = vm -CC = gcc -# on Linux, the following can be used with gcc: -# CFLAGS = -fsanitize=address -static-libasan -g -std=c17 -Wall -CFLAGS = -g -std=c17 -Wall -MV = mv -RM = rm -f -CHMOD = chmod -SUBMISSIONZIPFILE = submission.zip -ZIP = zip -9 -# Add the names of your own files with a .o suffix to link them into the VM -VM_OBJECTS = machine_main.o machine.o \ - machine_types.o instruction.o bof.o \ - regname.o utilities.o -TESTS = vm_test0.bof vm_test1.bof vm_test2.bof vm_test3.bof \ - vm_test4.bof vm_test5.bof vm_test6.bof vm_test7.bof \ - vm_test8.bof vm_test9.bof vm_testA.bof vm_testB.bof \ - vm_testC.bof vm_testD.bof vm_testE.bof -TESTSOURCES = $(TESTS:.bof=.asm) -EXPECTEDOUTPUTS = $(TESTS:.bof=.out) -EXPECTEDLISTINGS = $(TESTS:.bof=.lst) -# STUDENTESTOUTPUTS is all of the .myo files corresponding to the tests -# if you add more tests, you can add more to this list, -# or just add to TESTS above -STUDENTTESTOUTPUTS = $(TESTS:.bof=.myo) -# STUDENTESTLISTINGS is all of the .myp files corresponding to the tests -# if you add more tests, you can add more to this list, -# or just add to TESTS above -STUDENTTESTLISTINGS = $(TESTS:.bof=.myp) -# Don't remove these outputs if there are errors -.PRECIOUS: $(STUDENTTESTOUTPUTS) $(STUDENTTESTLISTINGS) - -# create the VM executable -.PRECIOUS: $(VM) - -$(VM): $(VM_OBJECTS) - $(CC) $(CFLAGS) -o $(VM) $(VM_OBJECTS) - -# rule for compiling individual .c files -%.o: %.c %.h - $(CC) $(CFLAGS) -c $< - -.PHONY: clean cleanall -clean: - $(RM) *~ *.o *.myo *.myp *.bof '#'* - $(RM) $(VM).exe $(VM) - $(RM) *.stackdump core - $(RM) $(SUBMISSIONZIPFILE) - -cleanall: clean - $(RM) $(ASM) $(ASM).exe $(DISASM) $(DISASM).exe - $(RM) test test.exe $(BOF_BIN_DUMP) $(BOF_BIN_DUMP).exe - -# rule for making .bof files with the assembler ($(ASM)); -# this might need to be done if not running on Linux (or Windows) - -%.bof: %.asm $(ASM) - ./$(ASM) $< - -# Rules for making individual outputs (e.g., execute make test1.myo) -# the .myo files are outputs from running the .bof files in the VM -.PRECIOUS: %.myo %.myp -%.myo: %.bof $(VM) - ./$(VM) -t $< > $@ 2>&1 - -%.myp: %.bof $(VM) - ./$(VM) -p $< > $@ 2>&1 - -# main target for testing -.PHONY: check-outputs -check-outputs: $(VM) $(ASM) $(TESTS) check-lst-outputs check-vm-outputs - @echo 'Be sure to look for two test summaries above (listings and execution)' - -check-lst-outputs check-asm-outputs: - @DIFFS=0; \ - for f in `echo $(TESTS) | sed -e 's/\\.bof//g'`; \ - do \ - echo listing "$$f.bof" using ./$(VM) -p ...; \ - ./$(VM) -p "$$f.bof" > "$$f.myp" 2>&1; \ - diff -w -B "$$f.lst" "$$f.myp" && echo 'passed!' \ - || { echo 'failed!'; DIFFS=1; }; \ - done; \ - if test 0 = $$DIFFS; \ - then \ - echo 'All listing tests passed!'; \ - else \ - echo 'Some listing test(s) failed!'; \ - fi - -check-vm-outputs: - @DIFFS=0; \ - for f in `echo $(TESTS) | sed -e 's/\\.bof//g'`; \ - do \ - echo running "$$f.bof" in the VM using ./$(VM) -t ...; \ - ./$(VM) -t "$$f.bof" > "$$f.myo" 2>&1; \ - diff -w -B "$$f.out" "$$f.myo" && echo 'passed!' \ - || { echo 'failed!'; DIFFS=1; }; \ - done; \ - if test 0 = $$DIFFS; \ - then \ - echo 'All VM execution tests passed!'; \ - else \ - echo 'Some VM execution test(s) failed!'; \ - fi - -# Automatically generate the submission zip file -$(SUBMISSIONZIPFILE): *.c *.h $(STUDENTTESTOUTPUTS) $(STUDENTTESTLISTINGS) \ - Makefile - $(ZIP) $@ $^ asm.y asm_lexer.l $(EXPECTEDOUTPUTS) $(EXPECTEDLISTINGS) $(TESTS) $(TESTSOURCES) - -# instructor's section below... - -ASM = asm -DISASM = disasm -BOF_BIN_DUMP = bof_bin_dump -LEX = flex -LEXFLAGS = -# the following line is just to jog the memory, it is not used -FLEX = $(LEX) -YACC = bison -YACCFLAGS = -Wall --locations -d -v -LEXER = lexer - -.DEFAULT: $(VM) - -$(ASM)_lexer.c: $(ASM)_lexer.l $(ASM).tab.h - $(LEX) $(LEXFLAGS) $< - -$(ASM)_lexer.o: $(ASM)_lexer.c ast.h $(ASM).tab.h utilities.h char_utilities.h file_location.h - $(CC) $(CFLAGS) -Wno-unused-but-set-variable -Wno-unused-function -c $< - -$(ASM).tab.o: $(ASM).tab.c $(ASM).tab.h - $(CC) $(CFLAGS) -Wno-unused-const-variable -c $< - -instruction.o: $(ASM).tab.h - -$(ASM).tab.c $(ASM).tab.h: $(ASM).y ast.h parser_types.h machine_types.h - $(RM) $(ASM).tab.h $(ASM).tab.c - $(YACC) $(YACCFLAGS) $(ASM).y - -lexer.o: lexer.c lexer.h $(ASM).tab.h - $(CC) $(CFLAGS) -c $< - -$(LEXER) : $(LEXER)_main.o $(LEXER).o $(ASM)_lexer.o ast.o $(ASM).tab.o file_location.o lexer.o utilities.o char_utilities.o - $(CC) $(CFLAGS) $^ -o $@ - -$(ASM)_main.o: $(ASM)_main.c $(ASM).tab.h ast.h parser_types.h machine_types.h - -ASM_OBJECTS = $(ASM)_main.o $(ASM).tab.o $(ASM)_lexer.o $(ASM)_unparser.o ast.o bof.o file_location.o lexer.o pass1.o assemble.o instruction.o machine_types.o regname.o symtab.o utilities.o char_utilities.o - -$(ASM): $(ASM).tab.h $(ASM_OBJECTS) - $(CC) $(CFLAGS) $^ -o $@ - -$(DISASM): disasm_main.o disasm.o instruction.o bof.o machine_types.o regname.o utilities.o - $(CC) $(CFLAGS) -o $(DISASM) $^ - -.PHONY: all -all: $(VM) $(ASM) $(DISASM) - -.PHONY: check-separately -check-separately: - $(CC) $(CFLAGS) -c *.c diff --git a/vm/Makefile-for-Instructor b/vm/Makefile-for-Instructor deleted file mode 100755 index 3009c95..0000000 --- a/vm/Makefile-for-Instructor +++ /dev/null @@ -1,113 +0,0 @@ -# $Id: Makefile-for-Instructor,v 1.3 2024/11/10 14:42:04 leavens Exp $ - -include Makefile - -$(BOF_BIN_DUMP): bof_bin_dump.o bof.o utilities.o - $(CC) $(CFLAGS) -o $(BOF_BIN_DUMP) $^ - -.PHONY: all -all: $(ASM).tab.h vm asm disasm bof_bin_dump - -.PRECIOUS: %.out %.lst -%.out: %.bof $(VM) - $(RM) $@ - - ./$(VM) -t $< > $@ 2>&1 - -%.lst: %.bof $(VM) - rm -f $@ - - ./$(VM) -p $< > $@ 2>&1 - -.PHONY: create-outputs -create-outputs: $(VM) $(ASM) $(TESTS) - $(MAKE) -f Makefile-for-Instructor create-vm-outputs - $(MAKE) -f Makefile-for-Instructor create-asm-outputs - -create-vm-outputs: $(VM) $(ASM) $(TESTS) - for f in `echo $(TESTS) | sed -e 's/\\.bof//g'`; \ - do \ - $(RM) "$$f.out"; \ - echo running "$$f.bof" " ... in the VM, with -t option"; \ - ./$(VM) -t "$$f.bof" > "$$f.out" 2>&1 || true ; \ - done - echo 'done creating VM test tracing outputs!' - -create-asm-outputs: $(VM) $(ASM) $(TESTS) - for f in `echo $(TESTS) | sed -e 's/\\.bof//g'`; \ - do \ - $(RM) "$$f.lst"; \ - echo running "$$f.bof" " ... in the VM, with -p option"; \ - ./$(VM) -p "$$f.bof" > "$$f.lst" 2>&1; \ - done - echo 'done creating listing outputs!' - -.PHONY: digest -digest digest.txt: $(EXPECTEDOUTPUTS) $(EXPECTEDLISTINGS) - for f in $(EXPECTEDLISTINGS) ; \ - do cat $$f; echo " "; \ - cat `echo $$f | sed -e 's/\\.lst/.out/'`; \ - echo " "; echo " "; \ - done >digest.txt - -# don't use develop-clean unless you want to regenerate the expected outputs -.PHONY: develop-clean bof-clean asm-clean -develop-clean: cleanall asm-clean - $(RM) digest.txt - $(RM) y.tab.h - -asm-clean: - $(RM) $(ASM)_lexer.[ch] $(ASM).tab.[ch] asm.output - $(RM) $(ASM).exe $(ASM) $(DISASM).exe $(DISASM) $(LEXER) $(LEXER).exe - $(RM) $(BOF_BIN_DUMP).exe $(BOF_BIN_DUMP) - -outputs-clean: clean asm-clean bof-clean - $(RM) $(EXPECTEDOUTPUTS) $(EXPECTEDLISTINGS) - -bof-clean: - $(RM) *.bof - -ZIPFILE = hw1-tests.zip -TESTSZIPFILE = ../$(ZIPFILE) -PROVIDEDFILES = Makefile asm_main.c asm.y asm_lexer.l \ - asm_lexer.c asm.tab.[ch] parser_types.h \ - asm_unparser.[ch] ast.[ch] bof.[ch] machine_types.[ch] \ - utilities.[ch] file_location.[ch] lexer.[ch] \ - pass1.[ch] assemble.[ch] instruction.[ch] regname.[ch] \ - symtab.[ch] utilities.[ch] char_utilities.[ch] \ - id_attrs_assoc.h disasm_main.c disasm.[ch] \ - vm_test*.asm vm_test*.out vm_test*.bof vm_test*.lst \ - bof_bin_dump.c - -PDFFILES = ../../ssm-vm.pdf ../../ssm-asm.pdf - -.PHONY: zip $(ZIPFILE) - -zip $(ZIPFILE): $(TESTSZIPFILE) - -$(TESTSZIPFILE): $(PDFFILES) Makefile $(TESTS) $(PROVIDEDFILES) $(VM) create-vm-outputs - $(RM) $(TESTSZIPFILE) - $(CHMOD) a-w *.lst *.asm *.bof *.lst *.[ch] \ - $(EXPECTEDOUTPUTS) $(EXPECTEDLISTINGS) - $(CHMOD) a+r Makefile $(TESTS) $(PROVIDEDFILES) - $(CHMOD) u+w Makefile asm.tab.h asm.tab.c - $(ZIP) $(TESTSZIPFILE) $(PDFFILES) Makefile $(TESTS) $(PROVIDEDFILES) - $(CHMOD) u+rw Makefile $(TESTS) $(PROVIDEDFILES) *.[ch] - -%.bof: %.$(ASM) - $(RM) -f $@ - ./$(ASM) $< - -SOLUTIONZIP = hw1-solution.zip - -.PHONY: $(SOLUTIONZIP) solution -$(SOLUTIONZIP) ~/temp/$(SOLUTIONZIP) solution: Makefile $(ASM) $(TESTS) \ - $(PROVIDEDFILES) *.out *.lst *.c *.h - $(MAKE) clean - $(ZIP) ~/temp/hw1-solution.zip $^ - -show_magic.o: bof.h - -show_magic: show_magic.o bof.o utilities.o - $(CC) $^ -o $@ - -test: test.o machine_types.o utilities.o - $(CC) $^ -o $@ diff --git a/vm/asm.output b/vm/asm.output deleted file mode 100644 index dd85311..0000000 --- a/vm/asm.output +++ /dev/null @@ -1,2091 +0,0 @@ -Grammar - - 0 $accept: program $end - - 1 program: textSection dataSection stackSection ".end" - - 2 textSection: ".text" entryPoint asmInstrs - - 3 entryPoint: addr - - 4 addr: label - 5 | unsignednumsym - - 6 label: identsym - - 7 asmInstrs: asmInstr - 8 | asmInstrs asmInstr - - 9 asmInstr: labelOpt instr eolsym - - 10 labelOpt: label ":" - 11 | empty - - 12 empty: ε - - 13 instr: noArgInstr - 14 | twoRegCompInstr - 15 | twoRegNoOffsetsInstr - 16 | noTargetOffsetInstr - 17 | noSourceOffsetInstr - 18 | oneRegOffsetArgInstr - 19 | oneRegArgInstr - 20 | oneRegOffsetInstr - 21 | shiftInstr - 22 | argOnlyInstr - 23 | immedArithInstr - 24 | immedBoolInstr - 25 | branchTestInstr - 26 | jumpInstr - 27 | syscallInstr - - 28 noArgInstr: noArgOp - - 29 noArgOp: "NOP" - 30 | "RTN" - - 31 twoRegCompInstr: twoRegCompOp regsym "," offset "," regsym "," offset - - 32 twoRegCompOp: "ADD" - 33 | "SUB" - 34 | "CPW" - 35 | "AND" - 36 | "BOR" - 37 | "NOR" - 38 | "XOR" - 39 | "SCA" - 40 | "LWI" - 41 | "NEG" - - 42 offset: number - - 43 number: sign unsignednumsym - - 44 sign: "+" - 45 | "-" - 46 | empty - - 47 twoRegNoOffsetsInstr: twoRegNoOffsetsOp regsym "," regsym - - 48 twoRegNoOffsetsOp: "CPR" - - 49 noTargetOffsetInstr: noTargetOffsetOp regsym "," regsym "," offset - - 50 noTargetOffsetOp: "LWR" - - 51 noSourceOffsetInstr: noSourceOffsetOp regsym "," offset "," regsym - - 52 noSourceOffsetOp: "SWR" - - 53 oneRegOffsetArgInstr: oneRegOffsetArgOp regsym "," offset "," arg - - 54 oneRegOffsetArgOp: "LIT" - - 55 arg: number - - 56 oneRegArgInstr: oneRegArgOp regsym "," arg - - 57 oneRegArgOp: "ARI" - 58 | "SRI" - - 59 oneRegOffsetInstr: oneRegOffsetOp regsym "," offset - - 60 oneRegOffsetOp: "MUL" - 61 | "DIV" - 62 | "CFHI" - 63 | "CFLO" - 64 | "JMP" - 65 | "CSI" - - 66 shiftInstr: shiftOp regsym "," offset "," shift - - 67 shiftOp: "SLL" - 68 | "SRL" - - 69 shift: unsignednumsym - - 70 argOnlyInstr: argOnlyOp arg - - 71 argOnlyOp: "JREL" - - 72 immedArithInstr: immedArithOp regsym "," offset "," immed - - 73 immedArithOp: "ADDI" - - 74 immed: number - - 75 immedBoolInstr: immedBoolOp regsym "," offset "," uimmed - - 76 immedBoolOp: "ANDI" - 77 | "BORI" - 78 | "XORI" - 79 | "NORI" - - 80 uimmed: unsignednumsym - - 81 branchTestInstr: branchTestOp regsym "," offset "," immed - - 82 branchTestOp: "BEQ" - 83 | "BGEZ" - 84 | "BGTZ" - 85 | "BLEZ" - 86 | "BLTZ" - 87 | "BNE" - - 88 jumpInstr: jumpOp addr - - 89 jumpOp: "JMPA" - 90 | "CALL" - - 91 syscallInstr: offsetOnlySyscall - 92 | regOffsetSyscall - 93 | noArgSyscall - - 94 offsetOnlySyscall: offsetOnlySyscallOp offset - - 95 offsetOnlySyscallOp: "EXIT" - - 96 regOffsetSyscall: regOffsetSyscallOp regsym "," offset - - 97 regOffsetSyscallOp: "PSTR" - 98 | "PINT" - 99 | "PCH" - 100 | "RCH" - - 101 noArgSyscall: noArgSyscallOp - - 102 noArgSyscallOp: "STRA" - 103 | "NOTR" - - 104 dataSection: ".data" staticStartAddr staticDecls - - 105 staticStartAddr: unsignednumsym - - 106 staticDecls: empty - 107 | staticDecls staticDecl - - 108 staticDecl: dataSize identsym initializerOpt eolsym - - 109 dataSize: "WORD" - 110 | "CHAR" - 111 | "STRING" "[" unsignednumsym "]" - - 112 initializerOpt: "=" number - 113 | "=" charliteralsym - 114 | "=" stringliteralsym - 115 | empty - - 116 stackSection: ".stack" stackBottomAddr - - 117 stackBottomAddr: unsignednumsym - - -Terminals, with rules where they appear - - $end (0) 0 - error (256) - eolsym (258) 9 108 - identsym (259) 6 108 - unsignednumsym (260) 5 43 69 80 105 111 117 - "+" (261) 44 - "-" (262) 45 - "," (263) 31 47 49 51 53 56 59 66 72 75 81 96 - ".text" (264) 2 - ".data" (265) 104 - ".stack" (266) 116 - ".end" (267) 1 - ":" (268) 10 - "[" (269) 111 - "]" (270) 111 - "=" (271) 112 113 114 - "NOP" (272) 29 - "ADD" (273) 32 - "SUB" (274) 33 - "CPW" (275) 34 - "CPR" (276) 48 - "AND" (277) 35 - "BOR" (278) 36 - "NOR" (279) 37 - "XOR" (280) 38 - "LWR" (281) 50 - "SWR" (282) 52 - "SCA" (283) 39 - "LWI" (284) 40 - "NEG" (285) 41 - "LIT" (286) 54 - "ARI" (287) 57 - "SRI" (288) 58 - "MUL" (289) 60 - "DIV" (290) 61 - "CFHI" (291) 62 - "CFLO" (292) 63 - "SLL" (293) 67 - "SRL" (294) 68 - "JMP" (295) 64 - "JREL" (296) 71 - "ADDI" (297) 73 - "ANDI" (298) 76 - "BORI" (299) 77 - "NORI" (300) 79 - "XORI" (301) 78 - "BEQ" (302) 82 - "BGEZ" (303) 83 - "BLEZ" (304) 85 - "BGTZ" (305) 84 - "BLTZ" (306) 86 - "BNE" (307) 87 - "CSI" (308) 65 - "JMPA" (309) 89 - "CALL" (310) 90 - "RTN" (311) 30 - "EXIT" (312) 95 - "PSTR" (313) 97 - "PINT" (314) 98 - "PCH" (315) 99 - "RCH" (316) 100 - "STRA" (317) 102 - "NOTR" (318) 103 - regsym (319) 31 47 49 51 53 56 59 66 72 75 81 96 - "WORD" (320) 109 - "CHAR" (321) 110 - "STRING" (322) 111 - charliteralsym (323) 113 - stringliteralsym (324) 114 - - -Nonterminals, with rules where they appear - - $accept (70) - on left: 0 - program (71) - on left: 1 - on right: 0 - textSection (72) - on left: 2 - on right: 1 - entryPoint (73) - on left: 3 - on right: 2 - addr (74) - on left: 4 5 - on right: 3 88 - label (75) - on left: 6 - on right: 4 10 - asmInstrs (76) - on left: 7 8 - on right: 2 8 - asmInstr (77) - on left: 9 - on right: 7 8 - labelOpt (78) - on left: 10 11 - on right: 9 - empty (79) - on left: 12 - on right: 11 46 106 115 - instr (80) - on left: 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 - on right: 9 - noArgInstr (81) - on left: 28 - on right: 13 - noArgOp (82) - on left: 29 30 - on right: 28 - twoRegCompInstr (83) - on left: 31 - on right: 14 - twoRegCompOp (84) - on left: 32 33 34 35 36 37 38 39 40 41 - on right: 31 - offset (85) - on left: 42 - on right: 31 49 51 53 59 66 72 75 81 94 96 - number (86) - on left: 43 - on right: 42 55 74 112 - sign (87) - on left: 44 45 46 - on right: 43 - twoRegNoOffsetsInstr (88) - on left: 47 - on right: 15 - twoRegNoOffsetsOp (89) - on left: 48 - on right: 47 - noTargetOffsetInstr (90) - on left: 49 - on right: 16 - noTargetOffsetOp (91) - on left: 50 - on right: 49 - noSourceOffsetInstr (92) - on left: 51 - on right: 17 - noSourceOffsetOp (93) - on left: 52 - on right: 51 - oneRegOffsetArgInstr (94) - on left: 53 - on right: 18 - oneRegOffsetArgOp (95) - on left: 54 - on right: 53 - arg (96) - on left: 55 - on right: 53 56 70 - oneRegArgInstr (97) - on left: 56 - on right: 19 - oneRegArgOp (98) - on left: 57 58 - on right: 56 - oneRegOffsetInstr (99) - on left: 59 - on right: 20 - oneRegOffsetOp (100) - on left: 60 61 62 63 64 65 - on right: 59 - shiftInstr (101) - on left: 66 - on right: 21 - shiftOp (102) - on left: 67 68 - on right: 66 - shift (103) - on left: 69 - on right: 66 - argOnlyInstr (104) - on left: 70 - on right: 22 - argOnlyOp (105) - on left: 71 - on right: 70 - immedArithInstr (106) - on left: 72 - on right: 23 - immedArithOp (107) - on left: 73 - on right: 72 - immed (108) - on left: 74 - on right: 72 81 - immedBoolInstr (109) - on left: 75 - on right: 24 - immedBoolOp (110) - on left: 76 77 78 79 - on right: 75 - uimmed (111) - on left: 80 - on right: 75 - branchTestInstr (112) - on left: 81 - on right: 25 - branchTestOp (113) - on left: 82 83 84 85 86 87 - on right: 81 - jumpInstr (114) - on left: 88 - on right: 26 - jumpOp (115) - on left: 89 90 - on right: 88 - syscallInstr (116) - on left: 91 92 93 - on right: 27 - offsetOnlySyscall (117) - on left: 94 - on right: 91 - offsetOnlySyscallOp (118) - on left: 95 - on right: 94 - regOffsetSyscall (119) - on left: 96 - on right: 92 - regOffsetSyscallOp (120) - on left: 97 98 99 100 - on right: 96 - noArgSyscall (121) - on left: 101 - on right: 93 - noArgSyscallOp (122) - on left: 102 103 - on right: 101 - dataSection (123) - on left: 104 - on right: 1 - staticStartAddr (124) - on left: 105 - on right: 104 - staticDecls (125) - on left: 106 107 - on right: 104 107 - staticDecl (126) - on left: 108 - on right: 107 - dataSize (127) - on left: 109 110 111 - on right: 108 - initializerOpt (128) - on left: 112 113 114 115 - on right: 108 - stackSection (129) - on left: 116 - on right: 1 - stackBottomAddr (130) - on left: 117 - on right: 116 - - -State 0 - - 0 $accept: • program $end - - ".text" shift, and go to state 1 - - program go to state 2 - textSection go to state 3 - - -State 1 - - 2 textSection: ".text" • entryPoint asmInstrs - - identsym shift, and go to state 4 - unsignednumsym shift, and go to state 5 - - entryPoint go to state 6 - addr go to state 7 - label go to state 8 - - -State 2 - - 0 $accept: program • $end - - $end shift, and go to state 9 - - -State 3 - - 1 program: textSection • dataSection stackSection ".end" - - ".data" shift, and go to state 10 - - dataSection go to state 11 - - -State 4 - - 6 label: identsym • - - $default reduce using rule 6 (label) - - -State 5 - - 5 addr: unsignednumsym • - - $default reduce using rule 5 (addr) - - -State 6 - - 2 textSection: ".text" entryPoint • asmInstrs - - identsym shift, and go to state 4 - - $default reduce using rule 12 (empty) - - label go to state 12 - asmInstrs go to state 13 - asmInstr go to state 14 - labelOpt go to state 15 - empty go to state 16 - - -State 7 - - 3 entryPoint: addr • - - $default reduce using rule 3 (entryPoint) - - -State 8 - - 4 addr: label • - - $default reduce using rule 4 (addr) - - -State 9 - - 0 $accept: program $end • - - $default accept - - -State 10 - - 104 dataSection: ".data" • staticStartAddr staticDecls - - unsignednumsym shift, and go to state 17 - - staticStartAddr go to state 18 - - -State 11 - - 1 program: textSection dataSection • stackSection ".end" - - ".stack" shift, and go to state 19 - - stackSection go to state 20 - - -State 12 - - 10 labelOpt: label • ":" - - ":" shift, and go to state 21 - - -State 13 - - 2 textSection: ".text" entryPoint asmInstrs • - 8 asmInstrs: asmInstrs • asmInstr - - identsym shift, and go to state 4 - - ".data" reduce using rule 2 (textSection) - $default reduce using rule 12 (empty) - - label go to state 12 - asmInstr go to state 22 - labelOpt go to state 15 - empty go to state 16 - - -State 14 - - 7 asmInstrs: asmInstr • - - $default reduce using rule 7 (asmInstrs) - - -State 15 - - 9 asmInstr: labelOpt • instr eolsym - - "NOP" shift, and go to state 23 - "ADD" shift, and go to state 24 - "SUB" shift, and go to state 25 - "CPW" shift, and go to state 26 - "CPR" shift, and go to state 27 - "AND" shift, and go to state 28 - "BOR" shift, and go to state 29 - "NOR" shift, and go to state 30 - "XOR" shift, and go to state 31 - "LWR" shift, and go to state 32 - "SWR" shift, and go to state 33 - "SCA" shift, and go to state 34 - "LWI" shift, and go to state 35 - "NEG" shift, and go to state 36 - "LIT" shift, and go to state 37 - "ARI" shift, and go to state 38 - "SRI" shift, and go to state 39 - "MUL" shift, and go to state 40 - "DIV" shift, and go to state 41 - "CFHI" shift, and go to state 42 - "CFLO" shift, and go to state 43 - "SLL" shift, and go to state 44 - "SRL" shift, and go to state 45 - "JMP" shift, and go to state 46 - "JREL" shift, and go to state 47 - "ADDI" shift, and go to state 48 - "ANDI" shift, and go to state 49 - "BORI" shift, and go to state 50 - "NORI" shift, and go to state 51 - "XORI" shift, and go to state 52 - "BEQ" shift, and go to state 53 - "BGEZ" shift, and go to state 54 - "BLEZ" shift, and go to state 55 - "BGTZ" shift, and go to state 56 - "BLTZ" shift, and go to state 57 - "BNE" shift, and go to state 58 - "CSI" shift, and go to state 59 - "JMPA" shift, and go to state 60 - "CALL" shift, and go to state 61 - "RTN" shift, and go to state 62 - "EXIT" shift, and go to state 63 - "PSTR" shift, and go to state 64 - "PINT" shift, and go to state 65 - "PCH" shift, and go to state 66 - "RCH" shift, and go to state 67 - "STRA" shift, and go to state 68 - "NOTR" shift, and go to state 69 - - instr go to state 70 - noArgInstr go to state 71 - noArgOp go to state 72 - twoRegCompInstr go to state 73 - twoRegCompOp go to state 74 - twoRegNoOffsetsInstr go to state 75 - twoRegNoOffsetsOp go to state 76 - noTargetOffsetInstr go to state 77 - noTargetOffsetOp go to state 78 - noSourceOffsetInstr go to state 79 - noSourceOffsetOp go to state 80 - oneRegOffsetArgInstr go to state 81 - oneRegOffsetArgOp go to state 82 - oneRegArgInstr go to state 83 - oneRegArgOp go to state 84 - oneRegOffsetInstr go to state 85 - oneRegOffsetOp go to state 86 - shiftInstr go to state 87 - shiftOp go to state 88 - argOnlyInstr go to state 89 - argOnlyOp go to state 90 - immedArithInstr go to state 91 - immedArithOp go to state 92 - immedBoolInstr go to state 93 - immedBoolOp go to state 94 - branchTestInstr go to state 95 - branchTestOp go to state 96 - jumpInstr go to state 97 - jumpOp go to state 98 - syscallInstr go to state 99 - offsetOnlySyscall go to state 100 - offsetOnlySyscallOp go to state 101 - regOffsetSyscall go to state 102 - regOffsetSyscallOp go to state 103 - noArgSyscall go to state 104 - noArgSyscallOp go to state 105 - - -State 16 - - 11 labelOpt: empty • - - $default reduce using rule 11 (labelOpt) - - -State 17 - - 105 staticStartAddr: unsignednumsym • - - $default reduce using rule 105 (staticStartAddr) - - -State 18 - - 104 dataSection: ".data" staticStartAddr • staticDecls - - $default reduce using rule 12 (empty) - - empty go to state 106 - staticDecls go to state 107 - - -State 19 - - 116 stackSection: ".stack" • stackBottomAddr - - unsignednumsym shift, and go to state 108 - - stackBottomAddr go to state 109 - - -State 20 - - 1 program: textSection dataSection stackSection • ".end" - - ".end" shift, and go to state 110 - - -State 21 - - 10 labelOpt: label ":" • - - $default reduce using rule 10 (labelOpt) - - -State 22 - - 8 asmInstrs: asmInstrs asmInstr • - - $default reduce using rule 8 (asmInstrs) - - -State 23 - - 29 noArgOp: "NOP" • - - $default reduce using rule 29 (noArgOp) - - -State 24 - - 32 twoRegCompOp: "ADD" • - - $default reduce using rule 32 (twoRegCompOp) - - -State 25 - - 33 twoRegCompOp: "SUB" • - - $default reduce using rule 33 (twoRegCompOp) - - -State 26 - - 34 twoRegCompOp: "CPW" • - - $default reduce using rule 34 (twoRegCompOp) - - -State 27 - - 48 twoRegNoOffsetsOp: "CPR" • - - $default reduce using rule 48 (twoRegNoOffsetsOp) - - -State 28 - - 35 twoRegCompOp: "AND" • - - $default reduce using rule 35 (twoRegCompOp) - - -State 29 - - 36 twoRegCompOp: "BOR" • - - $default reduce using rule 36 (twoRegCompOp) - - -State 30 - - 37 twoRegCompOp: "NOR" • - - $default reduce using rule 37 (twoRegCompOp) - - -State 31 - - 38 twoRegCompOp: "XOR" • - - $default reduce using rule 38 (twoRegCompOp) - - -State 32 - - 50 noTargetOffsetOp: "LWR" • - - $default reduce using rule 50 (noTargetOffsetOp) - - -State 33 - - 52 noSourceOffsetOp: "SWR" • - - $default reduce using rule 52 (noSourceOffsetOp) - - -State 34 - - 39 twoRegCompOp: "SCA" • - - $default reduce using rule 39 (twoRegCompOp) - - -State 35 - - 40 twoRegCompOp: "LWI" • - - $default reduce using rule 40 (twoRegCompOp) - - -State 36 - - 41 twoRegCompOp: "NEG" • - - $default reduce using rule 41 (twoRegCompOp) - - -State 37 - - 54 oneRegOffsetArgOp: "LIT" • - - $default reduce using rule 54 (oneRegOffsetArgOp) - - -State 38 - - 57 oneRegArgOp: "ARI" • - - $default reduce using rule 57 (oneRegArgOp) - - -State 39 - - 58 oneRegArgOp: "SRI" • - - $default reduce using rule 58 (oneRegArgOp) - - -State 40 - - 60 oneRegOffsetOp: "MUL" • - - $default reduce using rule 60 (oneRegOffsetOp) - - -State 41 - - 61 oneRegOffsetOp: "DIV" • - - $default reduce using rule 61 (oneRegOffsetOp) - - -State 42 - - 62 oneRegOffsetOp: "CFHI" • - - $default reduce using rule 62 (oneRegOffsetOp) - - -State 43 - - 63 oneRegOffsetOp: "CFLO" • - - $default reduce using rule 63 (oneRegOffsetOp) - - -State 44 - - 67 shiftOp: "SLL" • - - $default reduce using rule 67 (shiftOp) - - -State 45 - - 68 shiftOp: "SRL" • - - $default reduce using rule 68 (shiftOp) - - -State 46 - - 64 oneRegOffsetOp: "JMP" • - - $default reduce using rule 64 (oneRegOffsetOp) - - -State 47 - - 71 argOnlyOp: "JREL" • - - $default reduce using rule 71 (argOnlyOp) - - -State 48 - - 73 immedArithOp: "ADDI" • - - $default reduce using rule 73 (immedArithOp) - - -State 49 - - 76 immedBoolOp: "ANDI" • - - $default reduce using rule 76 (immedBoolOp) - - -State 50 - - 77 immedBoolOp: "BORI" • - - $default reduce using rule 77 (immedBoolOp) - - -State 51 - - 79 immedBoolOp: "NORI" • - - $default reduce using rule 79 (immedBoolOp) - - -State 52 - - 78 immedBoolOp: "XORI" • - - $default reduce using rule 78 (immedBoolOp) - - -State 53 - - 82 branchTestOp: "BEQ" • - - $default reduce using rule 82 (branchTestOp) - - -State 54 - - 83 branchTestOp: "BGEZ" • - - $default reduce using rule 83 (branchTestOp) - - -State 55 - - 85 branchTestOp: "BLEZ" • - - $default reduce using rule 85 (branchTestOp) - - -State 56 - - 84 branchTestOp: "BGTZ" • - - $default reduce using rule 84 (branchTestOp) - - -State 57 - - 86 branchTestOp: "BLTZ" • - - $default reduce using rule 86 (branchTestOp) - - -State 58 - - 87 branchTestOp: "BNE" • - - $default reduce using rule 87 (branchTestOp) - - -State 59 - - 65 oneRegOffsetOp: "CSI" • - - $default reduce using rule 65 (oneRegOffsetOp) - - -State 60 - - 89 jumpOp: "JMPA" • - - $default reduce using rule 89 (jumpOp) - - -State 61 - - 90 jumpOp: "CALL" • - - $default reduce using rule 90 (jumpOp) - - -State 62 - - 30 noArgOp: "RTN" • - - $default reduce using rule 30 (noArgOp) - - -State 63 - - 95 offsetOnlySyscallOp: "EXIT" • - - $default reduce using rule 95 (offsetOnlySyscallOp) - - -State 64 - - 97 regOffsetSyscallOp: "PSTR" • - - $default reduce using rule 97 (regOffsetSyscallOp) - - -State 65 - - 98 regOffsetSyscallOp: "PINT" • - - $default reduce using rule 98 (regOffsetSyscallOp) - - -State 66 - - 99 regOffsetSyscallOp: "PCH" • - - $default reduce using rule 99 (regOffsetSyscallOp) - - -State 67 - - 100 regOffsetSyscallOp: "RCH" • - - $default reduce using rule 100 (regOffsetSyscallOp) - - -State 68 - - 102 noArgSyscallOp: "STRA" • - - $default reduce using rule 102 (noArgSyscallOp) - - -State 69 - - 103 noArgSyscallOp: "NOTR" • - - $default reduce using rule 103 (noArgSyscallOp) - - -State 70 - - 9 asmInstr: labelOpt instr • eolsym - - eolsym shift, and go to state 111 - - -State 71 - - 13 instr: noArgInstr • - - $default reduce using rule 13 (instr) - - -State 72 - - 28 noArgInstr: noArgOp • - - $default reduce using rule 28 (noArgInstr) - - -State 73 - - 14 instr: twoRegCompInstr • - - $default reduce using rule 14 (instr) - - -State 74 - - 31 twoRegCompInstr: twoRegCompOp • regsym "," offset "," regsym "," offset - - regsym shift, and go to state 112 - - -State 75 - - 15 instr: twoRegNoOffsetsInstr • - - $default reduce using rule 15 (instr) - - -State 76 - - 47 twoRegNoOffsetsInstr: twoRegNoOffsetsOp • regsym "," regsym - - regsym shift, and go to state 113 - - -State 77 - - 16 instr: noTargetOffsetInstr • - - $default reduce using rule 16 (instr) - - -State 78 - - 49 noTargetOffsetInstr: noTargetOffsetOp • regsym "," regsym "," offset - - regsym shift, and go to state 114 - - -State 79 - - 17 instr: noSourceOffsetInstr • - - $default reduce using rule 17 (instr) - - -State 80 - - 51 noSourceOffsetInstr: noSourceOffsetOp • regsym "," offset "," regsym - - regsym shift, and go to state 115 - - -State 81 - - 18 instr: oneRegOffsetArgInstr • - - $default reduce using rule 18 (instr) - - -State 82 - - 53 oneRegOffsetArgInstr: oneRegOffsetArgOp • regsym "," offset "," arg - - regsym shift, and go to state 116 - - -State 83 - - 19 instr: oneRegArgInstr • - - $default reduce using rule 19 (instr) - - -State 84 - - 56 oneRegArgInstr: oneRegArgOp • regsym "," arg - - regsym shift, and go to state 117 - - -State 85 - - 20 instr: oneRegOffsetInstr • - - $default reduce using rule 20 (instr) - - -State 86 - - 59 oneRegOffsetInstr: oneRegOffsetOp • regsym "," offset - - regsym shift, and go to state 118 - - -State 87 - - 21 instr: shiftInstr • - - $default reduce using rule 21 (instr) - - -State 88 - - 66 shiftInstr: shiftOp • regsym "," offset "," shift - - regsym shift, and go to state 119 - - -State 89 - - 22 instr: argOnlyInstr • - - $default reduce using rule 22 (instr) - - -State 90 - - 70 argOnlyInstr: argOnlyOp • arg - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - number go to state 123 - sign go to state 124 - arg go to state 125 - - -State 91 - - 23 instr: immedArithInstr • - - $default reduce using rule 23 (instr) - - -State 92 - - 72 immedArithInstr: immedArithOp • regsym "," offset "," immed - - regsym shift, and go to state 126 - - -State 93 - - 24 instr: immedBoolInstr • - - $default reduce using rule 24 (instr) - - -State 94 - - 75 immedBoolInstr: immedBoolOp • regsym "," offset "," uimmed - - regsym shift, and go to state 127 - - -State 95 - - 25 instr: branchTestInstr • - - $default reduce using rule 25 (instr) - - -State 96 - - 81 branchTestInstr: branchTestOp • regsym "," offset "," immed - - regsym shift, and go to state 128 - - -State 97 - - 26 instr: jumpInstr • - - $default reduce using rule 26 (instr) - - -State 98 - - 88 jumpInstr: jumpOp • addr - - identsym shift, and go to state 4 - unsignednumsym shift, and go to state 5 - - addr go to state 129 - label go to state 8 - - -State 99 - - 27 instr: syscallInstr • - - $default reduce using rule 27 (instr) - - -State 100 - - 91 syscallInstr: offsetOnlySyscall • - - $default reduce using rule 91 (syscallInstr) - - -State 101 - - 94 offsetOnlySyscall: offsetOnlySyscallOp • offset - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 130 - number go to state 131 - sign go to state 124 - - -State 102 - - 92 syscallInstr: regOffsetSyscall • - - $default reduce using rule 92 (syscallInstr) - - -State 103 - - 96 regOffsetSyscall: regOffsetSyscallOp • regsym "," offset - - regsym shift, and go to state 132 - - -State 104 - - 93 syscallInstr: noArgSyscall • - - $default reduce using rule 93 (syscallInstr) - - -State 105 - - 101 noArgSyscall: noArgSyscallOp • - - $default reduce using rule 101 (noArgSyscall) - - -State 106 - - 106 staticDecls: empty • - - $default reduce using rule 106 (staticDecls) - - -State 107 - - 104 dataSection: ".data" staticStartAddr staticDecls • - 107 staticDecls: staticDecls • staticDecl - - "WORD" shift, and go to state 133 - "CHAR" shift, and go to state 134 - "STRING" shift, and go to state 135 - - $default reduce using rule 104 (dataSection) - - staticDecl go to state 136 - dataSize go to state 137 - - -State 108 - - 117 stackBottomAddr: unsignednumsym • - - $default reduce using rule 117 (stackBottomAddr) - - -State 109 - - 116 stackSection: ".stack" stackBottomAddr • - - $default reduce using rule 116 (stackSection) - - -State 110 - - 1 program: textSection dataSection stackSection ".end" • - - $default reduce using rule 1 (program) - - -State 111 - - 9 asmInstr: labelOpt instr eolsym • - - $default reduce using rule 9 (asmInstr) - - -State 112 - - 31 twoRegCompInstr: twoRegCompOp regsym • "," offset "," regsym "," offset - - "," shift, and go to state 138 - - -State 113 - - 47 twoRegNoOffsetsInstr: twoRegNoOffsetsOp regsym • "," regsym - - "," shift, and go to state 139 - - -State 114 - - 49 noTargetOffsetInstr: noTargetOffsetOp regsym • "," regsym "," offset - - "," shift, and go to state 140 - - -State 115 - - 51 noSourceOffsetInstr: noSourceOffsetOp regsym • "," offset "," regsym - - "," shift, and go to state 141 - - -State 116 - - 53 oneRegOffsetArgInstr: oneRegOffsetArgOp regsym • "," offset "," arg - - "," shift, and go to state 142 - - -State 117 - - 56 oneRegArgInstr: oneRegArgOp regsym • "," arg - - "," shift, and go to state 143 - - -State 118 - - 59 oneRegOffsetInstr: oneRegOffsetOp regsym • "," offset - - "," shift, and go to state 144 - - -State 119 - - 66 shiftInstr: shiftOp regsym • "," offset "," shift - - "," shift, and go to state 145 - - -State 120 - - 44 sign: "+" • - - $default reduce using rule 44 (sign) - - -State 121 - - 45 sign: "-" • - - $default reduce using rule 45 (sign) - - -State 122 - - 46 sign: empty • - - $default reduce using rule 46 (sign) - - -State 123 - - 55 arg: number • - - $default reduce using rule 55 (arg) - - -State 124 - - 43 number: sign • unsignednumsym - - unsignednumsym shift, and go to state 146 - - -State 125 - - 70 argOnlyInstr: argOnlyOp arg • - - $default reduce using rule 70 (argOnlyInstr) - - -State 126 - - 72 immedArithInstr: immedArithOp regsym • "," offset "," immed - - "," shift, and go to state 147 - - -State 127 - - 75 immedBoolInstr: immedBoolOp regsym • "," offset "," uimmed - - "," shift, and go to state 148 - - -State 128 - - 81 branchTestInstr: branchTestOp regsym • "," offset "," immed - - "," shift, and go to state 149 - - -State 129 - - 88 jumpInstr: jumpOp addr • - - $default reduce using rule 88 (jumpInstr) - - -State 130 - - 94 offsetOnlySyscall: offsetOnlySyscallOp offset • - - $default reduce using rule 94 (offsetOnlySyscall) - - -State 131 - - 42 offset: number • - - $default reduce using rule 42 (offset) - - -State 132 - - 96 regOffsetSyscall: regOffsetSyscallOp regsym • "," offset - - "," shift, and go to state 150 - - -State 133 - - 109 dataSize: "WORD" • - - $default reduce using rule 109 (dataSize) - - -State 134 - - 110 dataSize: "CHAR" • - - $default reduce using rule 110 (dataSize) - - -State 135 - - 111 dataSize: "STRING" • "[" unsignednumsym "]" - - "[" shift, and go to state 151 - - -State 136 - - 107 staticDecls: staticDecls staticDecl • - - $default reduce using rule 107 (staticDecls) - - -State 137 - - 108 staticDecl: dataSize • identsym initializerOpt eolsym - - identsym shift, and go to state 152 - - -State 138 - - 31 twoRegCompInstr: twoRegCompOp regsym "," • offset "," regsym "," offset - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 153 - number go to state 131 - sign go to state 124 - - -State 139 - - 47 twoRegNoOffsetsInstr: twoRegNoOffsetsOp regsym "," • regsym - - regsym shift, and go to state 154 - - -State 140 - - 49 noTargetOffsetInstr: noTargetOffsetOp regsym "," • regsym "," offset - - regsym shift, and go to state 155 - - -State 141 - - 51 noSourceOffsetInstr: noSourceOffsetOp regsym "," • offset "," regsym - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 156 - number go to state 131 - sign go to state 124 - - -State 142 - - 53 oneRegOffsetArgInstr: oneRegOffsetArgOp regsym "," • offset "," arg - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 157 - number go to state 131 - sign go to state 124 - - -State 143 - - 56 oneRegArgInstr: oneRegArgOp regsym "," • arg - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - number go to state 123 - sign go to state 124 - arg go to state 158 - - -State 144 - - 59 oneRegOffsetInstr: oneRegOffsetOp regsym "," • offset - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 159 - number go to state 131 - sign go to state 124 - - -State 145 - - 66 shiftInstr: shiftOp regsym "," • offset "," shift - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 160 - number go to state 131 - sign go to state 124 - - -State 146 - - 43 number: sign unsignednumsym • - - $default reduce using rule 43 (number) - - -State 147 - - 72 immedArithInstr: immedArithOp regsym "," • offset "," immed - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 161 - number go to state 131 - sign go to state 124 - - -State 148 - - 75 immedBoolInstr: immedBoolOp regsym "," • offset "," uimmed - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 162 - number go to state 131 - sign go to state 124 - - -State 149 - - 81 branchTestInstr: branchTestOp regsym "," • offset "," immed - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 163 - number go to state 131 - sign go to state 124 - - -State 150 - - 96 regOffsetSyscall: regOffsetSyscallOp regsym "," • offset - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 164 - number go to state 131 - sign go to state 124 - - -State 151 - - 111 dataSize: "STRING" "[" • unsignednumsym "]" - - unsignednumsym shift, and go to state 165 - - -State 152 - - 108 staticDecl: dataSize identsym • initializerOpt eolsym - - "=" shift, and go to state 166 - - $default reduce using rule 12 (empty) - - empty go to state 167 - initializerOpt go to state 168 - - -State 153 - - 31 twoRegCompInstr: twoRegCompOp regsym "," offset • "," regsym "," offset - - "," shift, and go to state 169 - - -State 154 - - 47 twoRegNoOffsetsInstr: twoRegNoOffsetsOp regsym "," regsym • - - $default reduce using rule 47 (twoRegNoOffsetsInstr) - - -State 155 - - 49 noTargetOffsetInstr: noTargetOffsetOp regsym "," regsym • "," offset - - "," shift, and go to state 170 - - -State 156 - - 51 noSourceOffsetInstr: noSourceOffsetOp regsym "," offset • "," regsym - - "," shift, and go to state 171 - - -State 157 - - 53 oneRegOffsetArgInstr: oneRegOffsetArgOp regsym "," offset • "," arg - - "," shift, and go to state 172 - - -State 158 - - 56 oneRegArgInstr: oneRegArgOp regsym "," arg • - - $default reduce using rule 56 (oneRegArgInstr) - - -State 159 - - 59 oneRegOffsetInstr: oneRegOffsetOp regsym "," offset • - - $default reduce using rule 59 (oneRegOffsetInstr) - - -State 160 - - 66 shiftInstr: shiftOp regsym "," offset • "," shift - - "," shift, and go to state 173 - - -State 161 - - 72 immedArithInstr: immedArithOp regsym "," offset • "," immed - - "," shift, and go to state 174 - - -State 162 - - 75 immedBoolInstr: immedBoolOp regsym "," offset • "," uimmed - - "," shift, and go to state 175 - - -State 163 - - 81 branchTestInstr: branchTestOp regsym "," offset • "," immed - - "," shift, and go to state 176 - - -State 164 - - 96 regOffsetSyscall: regOffsetSyscallOp regsym "," offset • - - $default reduce using rule 96 (regOffsetSyscall) - - -State 165 - - 111 dataSize: "STRING" "[" unsignednumsym • "]" - - "]" shift, and go to state 177 - - -State 166 - - 112 initializerOpt: "=" • number - 113 | "=" • charliteralsym - 114 | "=" • stringliteralsym - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - charliteralsym shift, and go to state 178 - stringliteralsym shift, and go to state 179 - - $default reduce using rule 12 (empty) - - empty go to state 122 - number go to state 180 - sign go to state 124 - - -State 167 - - 115 initializerOpt: empty • - - $default reduce using rule 115 (initializerOpt) - - -State 168 - - 108 staticDecl: dataSize identsym initializerOpt • eolsym - - eolsym shift, and go to state 181 - - -State 169 - - 31 twoRegCompInstr: twoRegCompOp regsym "," offset "," • regsym "," offset - - regsym shift, and go to state 182 - - -State 170 - - 49 noTargetOffsetInstr: noTargetOffsetOp regsym "," regsym "," • offset - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 183 - number go to state 131 - sign go to state 124 - - -State 171 - - 51 noSourceOffsetInstr: noSourceOffsetOp regsym "," offset "," • regsym - - regsym shift, and go to state 184 - - -State 172 - - 53 oneRegOffsetArgInstr: oneRegOffsetArgOp regsym "," offset "," • arg - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - number go to state 123 - sign go to state 124 - arg go to state 185 - - -State 173 - - 66 shiftInstr: shiftOp regsym "," offset "," • shift - - unsignednumsym shift, and go to state 186 - - shift go to state 187 - - -State 174 - - 72 immedArithInstr: immedArithOp regsym "," offset "," • immed - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - number go to state 188 - sign go to state 124 - immed go to state 189 - - -State 175 - - 75 immedBoolInstr: immedBoolOp regsym "," offset "," • uimmed - - unsignednumsym shift, and go to state 190 - - uimmed go to state 191 - - -State 176 - - 81 branchTestInstr: branchTestOp regsym "," offset "," • immed - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - number go to state 188 - sign go to state 124 - immed go to state 192 - - -State 177 - - 111 dataSize: "STRING" "[" unsignednumsym "]" • - - $default reduce using rule 111 (dataSize) - - -State 178 - - 113 initializerOpt: "=" charliteralsym • - - $default reduce using rule 113 (initializerOpt) - - -State 179 - - 114 initializerOpt: "=" stringliteralsym • - - $default reduce using rule 114 (initializerOpt) - - -State 180 - - 112 initializerOpt: "=" number • - - $default reduce using rule 112 (initializerOpt) - - -State 181 - - 108 staticDecl: dataSize identsym initializerOpt eolsym • - - $default reduce using rule 108 (staticDecl) - - -State 182 - - 31 twoRegCompInstr: twoRegCompOp regsym "," offset "," regsym • "," offset - - "," shift, and go to state 193 - - -State 183 - - 49 noTargetOffsetInstr: noTargetOffsetOp regsym "," regsym "," offset • - - $default reduce using rule 49 (noTargetOffsetInstr) - - -State 184 - - 51 noSourceOffsetInstr: noSourceOffsetOp regsym "," offset "," regsym • - - $default reduce using rule 51 (noSourceOffsetInstr) - - -State 185 - - 53 oneRegOffsetArgInstr: oneRegOffsetArgOp regsym "," offset "," arg • - - $default reduce using rule 53 (oneRegOffsetArgInstr) - - -State 186 - - 69 shift: unsignednumsym • - - $default reduce using rule 69 (shift) - - -State 187 - - 66 shiftInstr: shiftOp regsym "," offset "," shift • - - $default reduce using rule 66 (shiftInstr) - - -State 188 - - 74 immed: number • - - $default reduce using rule 74 (immed) - - -State 189 - - 72 immedArithInstr: immedArithOp regsym "," offset "," immed • - - $default reduce using rule 72 (immedArithInstr) - - -State 190 - - 80 uimmed: unsignednumsym • - - $default reduce using rule 80 (uimmed) - - -State 191 - - 75 immedBoolInstr: immedBoolOp regsym "," offset "," uimmed • - - $default reduce using rule 75 (immedBoolInstr) - - -State 192 - - 81 branchTestInstr: branchTestOp regsym "," offset "," immed • - - $default reduce using rule 81 (branchTestInstr) - - -State 193 - - 31 twoRegCompInstr: twoRegCompOp regsym "," offset "," regsym "," • offset - - "+" shift, and go to state 120 - "-" shift, and go to state 121 - - $default reduce using rule 12 (empty) - - empty go to state 122 - offset go to state 194 - number go to state 131 - sign go to state 124 - - -State 194 - - 31 twoRegCompInstr: twoRegCompOp regsym "," offset "," regsym "," offset • - - $default reduce using rule 31 (twoRegCompInstr) diff --git a/vm/asm.tab.c b/vm/asm.tab.c deleted file mode 100755 index 11784b9..0000000 --- a/vm/asm.tab.c +++ /dev/null @@ -1,2533 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.8.2. */ - -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, - Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, - especially those whose name start with YY_ or yy_. They are - private implementation details that can be changed or removed. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output, and Bison version. */ -#define YYBISON 30802 - -/* Bison version string. */ -#define YYBISON_VERSION "3.8.2" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - -/* "%code top" blocks. */ -#line 3 "asm.y" - -#include - -#line 72 "asm.tab.c" - - - - -# ifndef YY_CAST -# ifdef __cplusplus -# define YY_CAST(Type, Val) static_cast (Val) -# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) -# else -# define YY_CAST(Type, Val) ((Type) (Val)) -# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) -# endif -# endif -# ifndef YY_NULLPTR -# if defined __cplusplus -# if 201103L <= __cplusplus -# define YY_NULLPTR nullptr -# else -# define YY_NULLPTR 0 -# endif -# else -# define YY_NULLPTR ((void*)0) -# endif -# endif - -#include "asm.tab.h" -/* Symbol kind. */ -enum yysymbol_kind_t -{ - YYSYMBOL_YYEMPTY = -2, - YYSYMBOL_YYEOF = 0, /* "end of file" */ - YYSYMBOL_YYerror = 1, /* error */ - YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ - YYSYMBOL_eolsym = 3, /* eolsym */ - YYSYMBOL_identsym = 4, /* identsym */ - YYSYMBOL_unsignednumsym = 5, /* unsignednumsym */ - YYSYMBOL_plussym = 6, /* "+" */ - YYSYMBOL_minussym = 7, /* "-" */ - YYSYMBOL_commasym = 8, /* "," */ - YYSYMBOL_dottextsym = 9, /* ".text" */ - YYSYMBOL_dotdatasym = 10, /* ".data" */ - YYSYMBOL_dotstacksym = 11, /* ".stack" */ - YYSYMBOL_dotendsym = 12, /* ".end" */ - YYSYMBOL_colonsym = 13, /* ":" */ - YYSYMBOL_lbracketsym = 14, /* "[" */ - YYSYMBOL_rbracketsym = 15, /* "]" */ - YYSYMBOL_equalsym = 16, /* "=" */ - YYSYMBOL_noopsym = 17, /* "NOP" */ - YYSYMBOL_addopsym = 18, /* "ADD" */ - YYSYMBOL_subopsym = 19, /* "SUB" */ - YYSYMBOL_cpwopsym = 20, /* "CPW" */ - YYSYMBOL_cpropsym = 21, /* "CPR" */ - YYSYMBOL_andopsym = 22, /* "AND" */ - YYSYMBOL_boropsym = 23, /* "BOR" */ - YYSYMBOL_noropsym = 24, /* "NOR" */ - YYSYMBOL_xoropsym = 25, /* "XOR" */ - YYSYMBOL_lwropsym = 26, /* "LWR" */ - YYSYMBOL_swropsym = 27, /* "SWR" */ - YYSYMBOL_scaopsym = 28, /* "SCA" */ - YYSYMBOL_lwiopsym = 29, /* "LWI" */ - YYSYMBOL_negopsym = 30, /* "NEG" */ - YYSYMBOL_litopsym = 31, /* "LIT" */ - YYSYMBOL_ariopsym = 32, /* "ARI" */ - YYSYMBOL_sriopsym = 33, /* "SRI" */ - YYSYMBOL_mulopsym = 34, /* "MUL" */ - YYSYMBOL_divopsym = 35, /* "DIV" */ - YYSYMBOL_cfhiopsym = 36, /* "CFHI" */ - YYSYMBOL_cfloopsym = 37, /* "CFLO" */ - YYSYMBOL_sllopsym = 38, /* "SLL" */ - YYSYMBOL_srlopsym = 39, /* "SRL" */ - YYSYMBOL_jmpopsym = 40, /* "JMP" */ - YYSYMBOL_jrelopsym = 41, /* "JREL" */ - YYSYMBOL_addiopsym = 42, /* "ADDI" */ - YYSYMBOL_andiopsym = 43, /* "ANDI" */ - YYSYMBOL_boriopsym = 44, /* "BORI" */ - YYSYMBOL_noriopsym = 45, /* "NORI" */ - YYSYMBOL_xoriopsym = 46, /* "XORI" */ - YYSYMBOL_beqopsym = 47, /* "BEQ" */ - YYSYMBOL_bgezopsym = 48, /* "BGEZ" */ - YYSYMBOL_blezopsym = 49, /* "BLEZ" */ - YYSYMBOL_bgtzopsym = 50, /* "BGTZ" */ - YYSYMBOL_bltzopsym = 51, /* "BLTZ" */ - YYSYMBOL_bneopsym = 52, /* "BNE" */ - YYSYMBOL_csiopsym = 53, /* "CSI" */ - YYSYMBOL_jmpaopsym = 54, /* "JMPA" */ - YYSYMBOL_callopsym = 55, /* "CALL" */ - YYSYMBOL_rtnopsym = 56, /* "RTN" */ - YYSYMBOL_exitopsym = 57, /* "EXIT" */ - YYSYMBOL_pstropsym = 58, /* "PSTR" */ - YYSYMBOL_pintopsym = 59, /* "PINT" */ - YYSYMBOL_pchopsym = 60, /* "PCH" */ - YYSYMBOL_rchopsym = 61, /* "RCH" */ - YYSYMBOL_straopsym = 62, /* "STRA" */ - YYSYMBOL_notropsym = 63, /* "NOTR" */ - YYSYMBOL_regsym = 64, /* regsym */ - YYSYMBOL_wordsym = 65, /* "WORD" */ - YYSYMBOL_charsym = 66, /* "CHAR" */ - YYSYMBOL_stringsym = 67, /* "STRING" */ - YYSYMBOL_charliteralsym = 68, /* charliteralsym */ - YYSYMBOL_stringliteralsym = 69, /* stringliteralsym */ - YYSYMBOL_YYACCEPT = 70, /* $accept */ - YYSYMBOL_program = 71, /* program */ - YYSYMBOL_textSection = 72, /* textSection */ - YYSYMBOL_entryPoint = 73, /* entryPoint */ - YYSYMBOL_addr = 74, /* addr */ - YYSYMBOL_label = 75, /* label */ - YYSYMBOL_asmInstrs = 76, /* asmInstrs */ - YYSYMBOL_asmInstr = 77, /* asmInstr */ - YYSYMBOL_labelOpt = 78, /* labelOpt */ - YYSYMBOL_empty = 79, /* empty */ - YYSYMBOL_instr = 80, /* instr */ - YYSYMBOL_noArgInstr = 81, /* noArgInstr */ - YYSYMBOL_noArgOp = 82, /* noArgOp */ - YYSYMBOL_twoRegCompInstr = 83, /* twoRegCompInstr */ - YYSYMBOL_twoRegCompOp = 84, /* twoRegCompOp */ - YYSYMBOL_offset = 85, /* offset */ - YYSYMBOL_number = 86, /* number */ - YYSYMBOL_sign = 87, /* sign */ - YYSYMBOL_twoRegNoOffsetsInstr = 88, /* twoRegNoOffsetsInstr */ - YYSYMBOL_twoRegNoOffsetsOp = 89, /* twoRegNoOffsetsOp */ - YYSYMBOL_noTargetOffsetInstr = 90, /* noTargetOffsetInstr */ - YYSYMBOL_noTargetOffsetOp = 91, /* noTargetOffsetOp */ - YYSYMBOL_noSourceOffsetInstr = 92, /* noSourceOffsetInstr */ - YYSYMBOL_noSourceOffsetOp = 93, /* noSourceOffsetOp */ - YYSYMBOL_oneRegOffsetArgInstr = 94, /* oneRegOffsetArgInstr */ - YYSYMBOL_oneRegOffsetArgOp = 95, /* oneRegOffsetArgOp */ - YYSYMBOL_arg = 96, /* arg */ - YYSYMBOL_oneRegArgInstr = 97, /* oneRegArgInstr */ - YYSYMBOL_oneRegArgOp = 98, /* oneRegArgOp */ - YYSYMBOL_oneRegOffsetInstr = 99, /* oneRegOffsetInstr */ - YYSYMBOL_oneRegOffsetOp = 100, /* oneRegOffsetOp */ - YYSYMBOL_shiftInstr = 101, /* shiftInstr */ - YYSYMBOL_shiftOp = 102, /* shiftOp */ - YYSYMBOL_shift = 103, /* shift */ - YYSYMBOL_argOnlyInstr = 104, /* argOnlyInstr */ - YYSYMBOL_argOnlyOp = 105, /* argOnlyOp */ - YYSYMBOL_immedArithInstr = 106, /* immedArithInstr */ - YYSYMBOL_immedArithOp = 107, /* immedArithOp */ - YYSYMBOL_immed = 108, /* immed */ - YYSYMBOL_immedBoolInstr = 109, /* immedBoolInstr */ - YYSYMBOL_immedBoolOp = 110, /* immedBoolOp */ - YYSYMBOL_uimmed = 111, /* uimmed */ - YYSYMBOL_branchTestInstr = 112, /* branchTestInstr */ - YYSYMBOL_branchTestOp = 113, /* branchTestOp */ - YYSYMBOL_jumpInstr = 114, /* jumpInstr */ - YYSYMBOL_jumpOp = 115, /* jumpOp */ - YYSYMBOL_syscallInstr = 116, /* syscallInstr */ - YYSYMBOL_offsetOnlySyscall = 117, /* offsetOnlySyscall */ - YYSYMBOL_offsetOnlySyscallOp = 118, /* offsetOnlySyscallOp */ - YYSYMBOL_regOffsetSyscall = 119, /* regOffsetSyscall */ - YYSYMBOL_regOffsetSyscallOp = 120, /* regOffsetSyscallOp */ - YYSYMBOL_noArgSyscall = 121, /* noArgSyscall */ - YYSYMBOL_noArgSyscallOp = 122, /* noArgSyscallOp */ - YYSYMBOL_dataSection = 123, /* dataSection */ - YYSYMBOL_staticStartAddr = 124, /* staticStartAddr */ - YYSYMBOL_staticDecls = 125, /* staticDecls */ - YYSYMBOL_staticDecl = 126, /* staticDecl */ - YYSYMBOL_dataSize = 127, /* dataSize */ - YYSYMBOL_initializerOpt = 128, /* initializerOpt */ - YYSYMBOL_stackSection = 129, /* stackSection */ - YYSYMBOL_stackBottomAddr = 130 /* stackBottomAddr */ -}; -typedef enum yysymbol_kind_t yysymbol_kind_t; - - - -/* Unqualified %code blocks. */ -#line 160 "asm.y" - - /* extern declarations provided by the lexer */ -extern int yylex(void); - - /* extern void yyerror(char const *msg); */ - - /* The AST for the program, set by the semantic action for program. */ -ast_program_t progast; - - /* Set the program's ast to be t */ -extern void setProgAST(ast_program_t t); - -#line 253 "asm.tab.c" - -#ifdef short -# undef short -#endif - -/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure - and (if available) are included - so that the code can choose integer types of a good width. */ - -#ifndef __PTRDIFF_MAX__ -# include /* INFRINGES ON USER NAME SPACE */ -# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_STDINT_H -# endif -#endif - -/* Narrow types that promote to a signed type and that can represent a - signed or unsigned integer of at least N bits. In tables they can - save space and decrease cache pressure. Promoting to a signed type - helps avoid bugs in integer arithmetic. */ - -#ifdef __INT_LEAST8_MAX__ -typedef __INT_LEAST8_TYPE__ yytype_int8; -#elif defined YY_STDINT_H -typedef int_least8_t yytype_int8; -#else -typedef signed char yytype_int8; -#endif - -#ifdef __INT_LEAST16_MAX__ -typedef __INT_LEAST16_TYPE__ yytype_int16; -#elif defined YY_STDINT_H -typedef int_least16_t yytype_int16; -#else -typedef short yytype_int16; -#endif - -/* Work around bug in HP-UX 11.23, which defines these macros - incorrectly for preprocessor constants. This workaround can likely - be removed in 2023, as HPE has promised support for HP-UX 11.23 - (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of - . */ -#ifdef __hpux -# undef UINT_LEAST8_MAX -# undef UINT_LEAST16_MAX -# define UINT_LEAST8_MAX 255 -# define UINT_LEAST16_MAX 65535 -#endif - -#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ -typedef __UINT_LEAST8_TYPE__ yytype_uint8; -#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ - && UINT_LEAST8_MAX <= INT_MAX) -typedef uint_least8_t yytype_uint8; -#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX -typedef unsigned char yytype_uint8; -#else -typedef short yytype_uint8; -#endif - -#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ -typedef __UINT_LEAST16_TYPE__ yytype_uint16; -#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ - && UINT_LEAST16_MAX <= INT_MAX) -typedef uint_least16_t yytype_uint16; -#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX -typedef unsigned short yytype_uint16; -#else -typedef int yytype_uint16; -#endif - -#ifndef YYPTRDIFF_T -# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ -# define YYPTRDIFF_T __PTRDIFF_TYPE__ -# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ -# elif defined PTRDIFF_MAX -# ifndef ptrdiff_t -# include /* INFRINGES ON USER NAME SPACE */ -# endif -# define YYPTRDIFF_T ptrdiff_t -# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX -# else -# define YYPTRDIFF_T long -# define YYPTRDIFF_MAXIMUM LONG_MAX -# endif -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned -# endif -#endif - -#define YYSIZE_MAXIMUM \ - YY_CAST (YYPTRDIFF_T, \ - (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ - ? YYPTRDIFF_MAXIMUM \ - : YY_CAST (YYSIZE_T, -1))) - -#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) - - -/* Stored state numbers (used for stacks). */ -typedef yytype_uint8 yy_state_t; - -/* State numbers in computations. */ -typedef int yy_state_fast_t; - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) -# endif -# endif -# ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - - -#ifndef YY_ATTRIBUTE_PURE -# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) -# else -# define YY_ATTRIBUTE_PURE -# endif -#endif - -#ifndef YY_ATTRIBUTE_UNUSED -# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -# else -# define YY_ATTRIBUTE_UNUSED -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YY_USE(E) ((void) (E)) -#else -# define YY_USE(E) /* empty */ -#endif - -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ -# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") -# else -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# endif -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") -#else -# define YY_INITIAL_VALUE(Value) Value -#endif -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - -#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ -# define YY_IGNORE_USELESS_CAST_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") -# define YY_IGNORE_USELESS_CAST_END \ - _Pragma ("GCC diagnostic pop") -#endif -#ifndef YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_END -#endif - - -#define YY_ASSERT(E) ((void) (0 && (E))) - -#if 1 - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's 'empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -# define YYCOPY_NEEDED 1 -#endif /* 1 */ - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ - && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yy_state_t yyss_alloc; - YYSTYPE yyvs_alloc; - YYLTYPE yyls_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE) \ - + YYSIZEOF (YYLTYPE)) \ - + 2 * YYSTACK_GAP_MAXIMUM) - -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYPTRDIFF_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / YYSIZEOF (*yyptr); \ - } \ - while (0) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYPTRDIFF_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (0) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 9 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 146 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 70 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 61 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 118 -/* YYNSTATES -- Number of states. */ -#define YYNSTATES 195 - -/* YYMAXUTOK -- Last valid token kind. */ -#define YYMAXUTOK 324 - - -/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, with out-of-bounds checking. */ -#define YYTRANSLATE(YYX) \ - (0 <= (YYX) && (YYX) <= YYMAXUTOK \ - ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ - : YYSYMBOL_YYUNDEF) - -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex. */ -static const yytype_int8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 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 -}; - -#if YYDEBUG -/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_int16 yyrline[] = -{ - 0, 175, 175, 178, 182, 184, 185, 188, 191, 192, - 195, 197, 198, 201, 204, 204, 204, 205, 205, 205, - 206, 206, 206, 206, 207, 207, 207, 207, 208, 212, - 214, 214, 217, 225, 225, 225, 226, 226, 226, 226, - 226, 226, 226, 229, 236, 246, 246, 247, 251, 258, - 261, 268, 271, 278, 281, 290, 292, 300, 309, 309, - 312, 321, 321, 321, 321, 321, 321, 324, 333, 333, - 335, 343, 351, 354, 362, 364, 372, 380, 380, 380, - 380, 382, 390, 398, 398, 398, 398, 398, 398, 401, - 412, 412, 415, 415, 415, 417, 425, 428, 436, 436, - 436, 436, 439, 447, 447, 451, 455, 458, 459, 462, - 465, 466, 467, 472, 473, 475, 477, 481, 484 -}; -#endif - -/** Accessing symbol of state STATE. */ -#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) - -#if 1 -/* The user-facing name of the symbol whose (internal) number is - YYSYMBOL. No bounds checking. */ -static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; - -static const char * -yysymbol_name (yysymbol_kind_t yysymbol) -{ - static const char *const yy_sname[] = - { - "end of file", "error", "invalid token", "eolsym", "identsym", - "unsignednumsym", "+", "-", ",", ".text", ".data", ".stack", ".end", ":", - "[", "]", "=", "NOP", "ADD", "SUB", "CPW", "CPR", "AND", "BOR", "NOR", - "XOR", "LWR", "SWR", "SCA", "LWI", "NEG", "LIT", "ARI", "SRI", "MUL", - "DIV", "CFHI", "CFLO", "SLL", "SRL", "JMP", "JREL", "ADDI", "ANDI", - "BORI", "NORI", "XORI", "BEQ", "BGEZ", "BLEZ", "BGTZ", "BLTZ", "BNE", - "CSI", "JMPA", "CALL", "RTN", "EXIT", "PSTR", "PINT", "PCH", "RCH", - "STRA", "NOTR", "regsym", "WORD", "CHAR", "STRING", "charliteralsym", - "stringliteralsym", "$accept", "program", "textSection", "entryPoint", - "addr", "label", "asmInstrs", "asmInstr", "labelOpt", "empty", "instr", - "noArgInstr", "noArgOp", "twoRegCompInstr", "twoRegCompOp", "offset", - "number", "sign", "twoRegNoOffsetsInstr", "twoRegNoOffsetsOp", - "noTargetOffsetInstr", "noTargetOffsetOp", "noSourceOffsetInstr", - "noSourceOffsetOp", "oneRegOffsetArgInstr", "oneRegOffsetArgOp", "arg", - "oneRegArgInstr", "oneRegArgOp", "oneRegOffsetInstr", "oneRegOffsetOp", - "shiftInstr", "shiftOp", "shift", "argOnlyInstr", "argOnlyOp", - "immedArithInstr", "immedArithOp", "immed", "immedBoolInstr", - "immedBoolOp", "uimmed", "branchTestInstr", "branchTestOp", "jumpInstr", - "jumpOp", "syscallInstr", "offsetOnlySyscall", "offsetOnlySyscallOp", - "regOffsetSyscall", "regOffsetSyscallOp", "noArgSyscall", - "noArgSyscallOp", "dataSection", "staticStartAddr", "staticDecls", - "staticDecl", "dataSize", "initializerOpt", "stackSection", - "stackBottomAddr", YY_NULLPTR - }; - return yy_sname[yysymbol]; -} -#endif - -#define YYPACT_NINF (-140) - -#define yypact_value_is_default(Yyn) \ - ((Yyn) == YYPACT_NINF) - -#define YYTABLE_NINF (-4) - -#define yytable_value_is_error(Yyn) \ - 0 - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -static const yytype_int16 yypact[] = -{ - 10, 4, 5, 19, -140, -140, 26, -140, -140, -140, - 27, 20, 22, 6, -140, 71, -140, -140, -140, 29, - 24, -140, -140, -140, -140, -140, -140, -140, -140, -140, - -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, - -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, - -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, - -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, - 34, -140, -140, -140, -26, -140, -25, -140, -24, -140, - -23, -140, -22, -140, -20, -140, -19, -140, -18, -140, - 21, -140, -17, -140, -16, -140, -15, -140, 4, -140, - -140, 21, -140, -14, -140, -140, -140, -41, -140, -140, - -140, -140, 43, 44, 45, 47, 48, 49, 50, 51, - -140, -140, -140, -140, 55, -140, 53, 54, 59, -140, - -140, -140, 60, -140, -140, 56, -140, 65, 21, -1, - 7, 21, 21, 21, 21, 21, -140, 21, 21, 21, - 21, 67, 57, 66, -140, 68, 70, 72, -140, -140, - 73, 74, 76, 78, -140, 64, -4, -140, 132, 11, - 21, 75, 21, 131, 21, 133, 21, -140, -140, -140, - -140, -140, 129, -140, -140, -140, -140, -140, -140, -140, - -140, -140, -140, 21, -140 -}; - -/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ -static const yytype_int8 yydefact[] = -{ - 0, 0, 0, 0, 7, 6, 13, 4, 5, 1, - 0, 0, 0, 13, 8, 0, 12, 106, 13, 0, - 0, 11, 9, 30, 33, 34, 35, 49, 36, 37, - 38, 39, 51, 53, 40, 41, 42, 55, 58, 59, - 61, 62, 63, 64, 68, 69, 65, 72, 74, 77, - 78, 80, 79, 83, 84, 86, 85, 87, 88, 66, - 90, 91, 31, 96, 98, 99, 100, 101, 103, 104, - 0, 14, 29, 15, 0, 16, 0, 17, 0, 18, - 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, - 13, 24, 0, 25, 0, 26, 0, 27, 0, 28, - 92, 13, 93, 0, 94, 102, 107, 105, 118, 117, - 2, 10, 0, 0, 0, 0, 0, 0, 0, 0, - 45, 46, 47, 56, 0, 71, 0, 0, 0, 89, - 95, 43, 0, 110, 111, 0, 108, 0, 13, 0, - 0, 13, 13, 13, 13, 13, 44, 13, 13, 13, - 13, 0, 13, 0, 48, 0, 0, 0, 57, 60, - 0, 0, 0, 0, 97, 0, 13, 116, 0, 0, - 13, 0, 13, 0, 13, 0, 13, 112, 114, 115, - 113, 109, 0, 50, 52, 54, 70, 67, 75, 73, - 81, 76, 82, 13, 32 -}; - -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -140, -140, -140, -140, 42, 0, -140, 128, -140, -6, - -140, -140, -140, -140, -140, -127, -89, -140, -140, -140, - -140, -140, -140, -140, -140, -140, -139, -140, -140, -140, - -140, -140, -140, -140, -140, -140, -140, -140, -34, -140, - -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, - -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, - -140 -}; - -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_uint8 yydefgoto[] = -{ - 0, 2, 3, 6, 7, 8, 13, 14, 15, 122, - 70, 71, 72, 73, 74, 130, 131, 124, 75, 76, - 77, 78, 79, 80, 81, 82, 125, 83, 84, 85, - 86, 87, 88, 187, 89, 90, 91, 92, 189, 93, - 94, 191, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 11, 18, 107, 136, 137, 168, 20, - 109 -}; - -/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_int16 yytable[] = -{ - 16, 123, 120, 121, 158, 9, 12, 16, 4, 5, - 4, 153, 106, 12, 156, 157, -3, 159, 160, 1, - 161, 162, 163, 164, 133, 134, 135, 120, 121, 10, - 4, 19, 17, 185, 108, 21, 110, 111, 112, 113, - 114, 115, 116, 183, 117, 118, 119, 126, 127, 128, - 132, 138, 139, 140, 123, 141, 142, 143, 144, 145, - 146, 147, 148, 154, 178, 179, 194, 149, 150, 152, - 151, 155, 165, 166, 169, 182, 170, 180, 171, 177, - 172, 173, 174, 123, 175, 188, 176, 188, 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, 181, 186, 193, 190, 184, - 129, 22, 192, 0, 0, 0, 167 -}; - -static const yytype_int16 yycheck[] = -{ - 6, 90, 6, 7, 143, 0, 6, 13, 4, 5, - 4, 138, 18, 13, 141, 142, 10, 144, 145, 9, - 147, 148, 149, 150, 65, 66, 67, 6, 7, 10, - 4, 11, 5, 172, 5, 13, 12, 3, 64, 64, - 64, 64, 64, 170, 64, 64, 64, 64, 64, 64, - 64, 8, 8, 8, 143, 8, 8, 8, 8, 8, - 5, 8, 8, 64, 68, 69, 193, 8, 8, 4, - 14, 64, 5, 16, 8, 64, 8, 166, 8, 15, - 8, 8, 8, 172, 8, 174, 8, 176, 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, 3, 5, 8, 5, 64, - 98, 13, 176, -1, -1, -1, 152 -}; - -/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of - state STATE-NUM. */ -static const yytype_uint8 yystos[] = -{ - 0, 9, 71, 72, 4, 5, 73, 74, 75, 0, - 10, 123, 75, 76, 77, 78, 79, 5, 124, 11, - 129, 13, 77, 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, - 80, 81, 82, 83, 84, 88, 89, 90, 91, 92, - 93, 94, 95, 97, 98, 99, 100, 101, 102, 104, - 105, 106, 107, 109, 110, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 79, 125, 5, 130, - 12, 3, 64, 64, 64, 64, 64, 64, 64, 64, - 6, 7, 79, 86, 87, 96, 64, 64, 64, 74, - 85, 86, 64, 65, 66, 67, 126, 127, 8, 8, - 8, 8, 8, 8, 8, 8, 5, 8, 8, 8, - 8, 14, 4, 85, 64, 64, 85, 85, 96, 85, - 85, 85, 85, 85, 85, 5, 16, 79, 128, 8, - 8, 8, 8, 8, 8, 8, 8, 15, 68, 69, - 86, 3, 64, 85, 64, 96, 5, 103, 86, 108, - 5, 111, 108, 8, 85 -}; - -/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ -static const yytype_uint8 yyr1[] = -{ - 0, 70, 71, 72, 73, 74, 74, 75, 76, 76, - 77, 78, 78, 79, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, - 82, 82, 83, 84, 84, 84, 84, 84, 84, 84, - 84, 84, 84, 85, 86, 87, 87, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 98, - 99, 100, 100, 100, 100, 100, 100, 101, 102, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 110, 110, - 110, 111, 112, 113, 113, 113, 113, 113, 113, 114, - 115, 115, 116, 116, 116, 117, 118, 119, 120, 120, - 120, 120, 121, 122, 122, 123, 124, 125, 125, 126, - 127, 127, 127, 128, 128, 128, 128, 129, 130 -}; - -/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ -static const yytype_int8 yyr2[] = -{ - 0, 2, 4, 3, 1, 1, 1, 1, 1, 2, - 3, 2, 1, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 1, 1, 1, 4, 1, - 6, 1, 6, 1, 6, 1, 1, 4, 1, 1, - 4, 1, 1, 1, 1, 1, 1, 6, 1, 1, - 1, 2, 1, 6, 1, 1, 6, 1, 1, 1, - 1, 1, 6, 1, 1, 1, 1, 1, 1, 2, - 1, 1, 1, 1, 1, 2, 1, 4, 1, 1, - 1, 1, 1, 1, 1, 3, 1, 1, 2, 4, - 1, 1, 4, 2, 2, 2, 1, 2, 1 -}; - - -enum { YYENOMEM = -2 }; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab -#define YYNOMEM goto yyexhaustedlab - - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ - do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - YY_LAC_DISCARD ("YYBACKUP"); \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (file_name, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ - while (0) - -/* Backward compatibility with an undocumented macro. - Use YYerror or YYUNDEF. */ -#define YYERRCODE YYUNDEF - -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (N) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (0) -#endif - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - - -/* YYLOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -# ifndef YYLOCATION_PRINT - -# if defined YY_LOCATION_PRINT - - /* Temporary convenience wrapper in case some people defined the - undocumented and private YY_LOCATION_PRINT macros. */ -# define YYLOCATION_PRINT(File, Loc) YY_LOCATION_PRINT(File, *(Loc)) - -# elif defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL - -/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ - -YY_ATTRIBUTE_UNUSED -static int -yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) -{ - int res = 0; - int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; - if (0 <= yylocp->first_line) - { - res += YYFPRINTF (yyo, "%d", yylocp->first_line); - if (0 <= yylocp->first_column) - res += YYFPRINTF (yyo, ".%d", yylocp->first_column); - } - if (0 <= yylocp->last_line) - { - if (yylocp->first_line < yylocp->last_line) - { - res += YYFPRINTF (yyo, "-%d", yylocp->last_line); - if (0 <= end_col) - res += YYFPRINTF (yyo, ".%d", end_col); - } - else if (0 <= end_col && yylocp->first_column < end_col) - res += YYFPRINTF (yyo, "-%d", end_col); - } - return res; -} - -# define YYLOCATION_PRINT yy_location_print_ - - /* Temporary convenience wrapper in case some people defined the - undocumented and private YY_LOCATION_PRINT macros. */ -# define YY_LOCATION_PRINT(File, Loc) YYLOCATION_PRINT(File, &(Loc)) - -# else - -# define YYLOCATION_PRINT(File, Loc) ((void) 0) - /* Temporary convenience wrapper in case some people defined the - undocumented and private YY_LOCATION_PRINT macros. */ -# define YY_LOCATION_PRINT YYLOCATION_PRINT - -# endif -# endif /* !defined YYLOCATION_PRINT */ - - -# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Kind, Value, Location, file_name); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) - - -/*-----------------------------------. -| Print this symbol's value on YYO. | -`-----------------------------------*/ - -static void -yy_symbol_value_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, char const *file_name) -{ - FILE *yyoutput = yyo; - YY_USE (yyoutput); - YY_USE (yylocationp); - YY_USE (file_name); - if (!yyvaluep) - return; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YY_USE (yykind); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - -/*---------------------------. -| Print this symbol on YYO. | -`---------------------------*/ - -static void -yy_symbol_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, char const *file_name) -{ - YYFPRINTF (yyo, "%s %s (", - yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); - - YYLOCATION_PRINT (yyo, yylocationp); - YYFPRINTF (yyo, ": "); - yy_symbol_value_print (yyo, yykind, yyvaluep, yylocationp, file_name); - YYFPRINTF (yyo, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -static void -yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -static void -yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, - int yyrule, char const *file_name) -{ - int yylno = yyrline[yyrule]; - int yynrhs = yyr2[yyrule]; - int yyi; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, - YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), - &yyvsp[(yyi + 1) - (yynrhs)], - &(yylsp[(yyi + 1) - (yynrhs)]), file_name); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, yylsp, Rule, file_name); \ -} while (0) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) ((void) 0) -# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - -/* Given a state stack such that *YYBOTTOM is its bottom, such that - *YYTOP is either its top or is YYTOP_EMPTY to indicate an empty - stack, and such that *YYCAPACITY is the maximum number of elements it - can hold without a reallocation, make sure there is enough room to - store YYADD more elements. If not, allocate a new stack using - YYSTACK_ALLOC, copy the existing elements, and adjust *YYBOTTOM, - *YYTOP, and *YYCAPACITY to reflect the new capacity and memory - location. If *YYBOTTOM != YYBOTTOM_NO_FREE, then free the old stack - using YYSTACK_FREE. Return 0 if successful or if no reallocation is - required. Return YYENOMEM if memory is exhausted. */ -static int -yy_lac_stack_realloc (YYPTRDIFF_T *yycapacity, YYPTRDIFF_T yyadd, -#if YYDEBUG - char const *yydebug_prefix, - char const *yydebug_suffix, -#endif - yy_state_t **yybottom, - yy_state_t *yybottom_no_free, - yy_state_t **yytop, yy_state_t *yytop_empty) -{ - YYPTRDIFF_T yysize_old = - *yytop == yytop_empty ? 0 : *yytop - *yybottom + 1; - YYPTRDIFF_T yysize_new = yysize_old + yyadd; - if (*yycapacity < yysize_new) - { - YYPTRDIFF_T yyalloc = 2 * yysize_new; - yy_state_t *yybottom_new; - /* Use YYMAXDEPTH for maximum stack size given that the stack - should never need to grow larger than the main state stack - needs to grow without LAC. */ - if (YYMAXDEPTH < yysize_new) - { - YYDPRINTF ((stderr, "%smax size exceeded%s", yydebug_prefix, - yydebug_suffix)); - return YYENOMEM; - } - if (YYMAXDEPTH < yyalloc) - yyalloc = YYMAXDEPTH; - yybottom_new = - YY_CAST (yy_state_t *, - YYSTACK_ALLOC (YY_CAST (YYSIZE_T, - yyalloc * YYSIZEOF (*yybottom_new)))); - if (!yybottom_new) - { - YYDPRINTF ((stderr, "%srealloc failed%s", yydebug_prefix, - yydebug_suffix)); - return YYENOMEM; - } - if (*yytop != yytop_empty) - { - YYCOPY (yybottom_new, *yybottom, yysize_old); - *yytop = yybottom_new + (yysize_old - 1); - } - if (*yybottom != yybottom_no_free) - YYSTACK_FREE (*yybottom); - *yybottom = yybottom_new; - *yycapacity = yyalloc; - } - return 0; -} - -/* Establish the initial context for the current lookahead if no initial - context is currently established. - - We define a context as a snapshot of the parser stacks. We define - the initial context for a lookahead as the context in which the - parser initially examines that lookahead in order to select a - syntactic action. Thus, if the lookahead eventually proves - syntactically unacceptable (possibly in a later context reached via a - series of reductions), the initial context can be used to determine - the exact set of tokens that would be syntactically acceptable in the - lookahead's place. Moreover, it is the context after which any - further semantic actions would be erroneous because they would be - determined by a syntactically unacceptable token. - - YY_LAC_ESTABLISH should be invoked when a reduction is about to be - performed in an inconsistent state (which, for the purposes of LAC, - includes consistent states that don't know they're consistent because - their default reductions have been disabled). Iff there is a - lookahead token, it should also be invoked before reporting a syntax - error. This latter case is for the sake of the debugging output. - - For parse.lac=full, the implementation of YY_LAC_ESTABLISH is as - follows. If no initial context is currently established for the - current lookahead, then check if that lookahead can eventually be - shifted if syntactic actions continue from the current context. - Report a syntax error if it cannot. */ -#define YY_LAC_ESTABLISH \ -do { \ - if (!yy_lac_established) \ - { \ - YYDPRINTF ((stderr, \ - "LAC: initial context established for %s\n", \ - yysymbol_name (yytoken))); \ - yy_lac_established = 1; \ - switch (yy_lac (yyesa, &yyes, &yyes_capacity, yyssp, yytoken)) \ - { \ - case YYENOMEM: \ - YYNOMEM; \ - case 1: \ - goto yyerrlab; \ - } \ - } \ -} while (0) - -/* Discard any previous initial lookahead context because of Event, - which may be a lookahead change or an invalidation of the currently - established initial context for the current lookahead. - - The most common example of a lookahead change is a shift. An example - of both cases is syntax error recovery. That is, a syntax error - occurs when the lookahead is syntactically erroneous for the - currently established initial context, so error recovery manipulates - the parser stacks to try to find a new initial context in which the - current lookahead is syntactically acceptable. If it fails to find - such a context, it discards the lookahead. */ -#if YYDEBUG -# define YY_LAC_DISCARD(Event) \ -do { \ - if (yy_lac_established) \ - { \ - YYDPRINTF ((stderr, "LAC: initial context discarded due to " \ - Event "\n")); \ - yy_lac_established = 0; \ - } \ -} while (0) -#else -# define YY_LAC_DISCARD(Event) yy_lac_established = 0 -#endif - -/* Given the stack whose top is *YYSSP, return 0 iff YYTOKEN can - eventually (after perhaps some reductions) be shifted, return 1 if - not, or return YYENOMEM if memory is exhausted. As preconditions and - postconditions: *YYES_CAPACITY is the allocated size of the array to - which *YYES points, and either *YYES = YYESA or *YYES points to an - array allocated with YYSTACK_ALLOC. yy_lac may overwrite the - contents of either array, alter *YYES and *YYES_CAPACITY, and free - any old *YYES other than YYESA. */ -static int -yy_lac (yy_state_t *yyesa, yy_state_t **yyes, - YYPTRDIFF_T *yyes_capacity, yy_state_t *yyssp, yysymbol_kind_t yytoken) -{ - yy_state_t *yyes_prev = yyssp; - yy_state_t *yyesp = yyes_prev; - /* Reduce until we encounter a shift and thereby accept the token. */ - YYDPRINTF ((stderr, "LAC: checking lookahead %s:", yysymbol_name (yytoken))); - if (yytoken == YYSYMBOL_YYUNDEF) - { - YYDPRINTF ((stderr, " Always Err\n")); - return 1; - } - while (1) - { - int yyrule = yypact[+*yyesp]; - if (yypact_value_is_default (yyrule) - || (yyrule += yytoken) < 0 || YYLAST < yyrule - || yycheck[yyrule] != yytoken) - { - /* Use the default action. */ - yyrule = yydefact[+*yyesp]; - if (yyrule == 0) - { - YYDPRINTF ((stderr, " Err\n")); - return 1; - } - } - else - { - /* Use the action from yytable. */ - yyrule = yytable[yyrule]; - if (yytable_value_is_error (yyrule)) - { - YYDPRINTF ((stderr, " Err\n")); - return 1; - } - if (0 < yyrule) - { - YYDPRINTF ((stderr, " S%d\n", yyrule)); - return 0; - } - yyrule = -yyrule; - } - /* By now we know we have to simulate a reduce. */ - YYDPRINTF ((stderr, " R%d", yyrule - 1)); - { - /* Pop the corresponding number of values from the stack. */ - YYPTRDIFF_T yylen = yyr2[yyrule]; - /* First pop from the LAC stack as many tokens as possible. */ - if (yyesp != yyes_prev) - { - YYPTRDIFF_T yysize = yyesp - *yyes + 1; - if (yylen < yysize) - { - yyesp -= yylen; - yylen = 0; - } - else - { - yyesp = yyes_prev; - yylen -= yysize; - } - } - /* Only afterwards look at the main stack. */ - if (yylen) - yyesp = yyes_prev -= yylen; - } - /* Push the resulting state of the reduction. */ - { - yy_state_fast_t yystate; - { - const int yylhs = yyr1[yyrule] - YYNTOKENS; - const int yyi = yypgoto[yylhs] + *yyesp; - yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyesp - ? yytable[yyi] - : yydefgoto[yylhs]); - } - if (yyesp == yyes_prev) - { - yyesp = *yyes; - YY_IGNORE_USELESS_CAST_BEGIN - *yyesp = YY_CAST (yy_state_t, yystate); - YY_IGNORE_USELESS_CAST_END - } - else - { - if (yy_lac_stack_realloc (yyes_capacity, 1, -#if YYDEBUG - " (", ")", -#endif - yyes, yyesa, &yyesp, yyes_prev)) - { - YYDPRINTF ((stderr, "\n")); - return YYENOMEM; - } - YY_IGNORE_USELESS_CAST_BEGIN - *++yyesp = YY_CAST (yy_state_t, yystate); - YY_IGNORE_USELESS_CAST_END - } - YYDPRINTF ((stderr, " G%d", yystate)); - } - } -} - -/* Context of a parse error. */ -typedef struct -{ - yy_state_t *yyssp; - yy_state_t *yyesa; - yy_state_t **yyes; - YYPTRDIFF_T *yyes_capacity; - yysymbol_kind_t yytoken; - YYLTYPE *yylloc; -} yypcontext_t; - -/* Put in YYARG at most YYARGN of the expected tokens given the - current YYCTX, and return the number of tokens stored in YYARG. If - YYARG is null, return the number of expected tokens (guaranteed to - be less than YYNTOKENS). Return YYENOMEM on memory exhaustion. - Return 0 if there are more than YYARGN expected tokens, yet fill - YYARG up to YYARGN. */ -static int -yypcontext_expected_tokens (const yypcontext_t *yyctx, - yysymbol_kind_t yyarg[], int yyargn) -{ - /* Actual size of YYARG. */ - int yycount = 0; - - int yyx; - for (yyx = 0; yyx < YYNTOKENS; ++yyx) - { - yysymbol_kind_t yysym = YY_CAST (yysymbol_kind_t, yyx); - if (yysym != YYSYMBOL_YYerror && yysym != YYSYMBOL_YYUNDEF) - switch (yy_lac (yyctx->yyesa, yyctx->yyes, yyctx->yyes_capacity, yyctx->yyssp, yysym)) - { - case YYENOMEM: - return YYENOMEM; - case 1: - continue; - default: - if (!yyarg) - ++yycount; - else if (yycount == yyargn) - return 0; - else - yyarg[yycount++] = yysym; - } - } - if (yyarg && yycount == 0 && 0 < yyargn) - yyarg[0] = YYSYMBOL_YYEMPTY; - return yycount; -} - - - - -#ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S))) -# else -/* Return the length of YYSTR. */ -static YYPTRDIFF_T -yystrlen (const char *yystr) -{ - YYPTRDIFF_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -#endif - -#ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -yystpcpy (char *yydest, const char *yysrc) -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -#endif - - - -static int -yy_syntax_error_arguments (const yypcontext_t *yyctx, - yysymbol_kind_t yyarg[], int yyargn) -{ - /* Actual size of YYARG. */ - int yycount = 0; - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - In the first two cases, it might appear that the current syntax - error should have been detected in the previous state when yy_lac - was invoked. However, at that time, there might have been a - different syntax error that discarded a different initial context - during error recovery, leaving behind the current lookahead. - */ - if (yyctx->yytoken != YYSYMBOL_YYEMPTY) - { - int yyn; - YYDPRINTF ((stderr, "Constructing syntax error message\n")); - if (yyarg) - yyarg[yycount] = yyctx->yytoken; - ++yycount; - yyn = yypcontext_expected_tokens (yyctx, - yyarg ? yyarg + 1 : yyarg, yyargn - 1); - if (yyn == YYENOMEM) - return YYENOMEM; - else if (yyn == 0) - YYDPRINTF ((stderr, "No expected tokens.\n")); - else - yycount += yyn; - } - return yycount; -} - -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. In order to see if a particular token T is a - valid looakhead, invoke yy_lac (YYESA, YYES, YYES_CAPACITY, YYSSP, T). - - Return 0 if *YYMSG was successfully written. Return -1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return YYENOMEM if the - required number of bytes is too large to store or if - yy_lac returned YYENOMEM. */ -static int -yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg, - const yypcontext_t *yyctx) -{ - enum { YYARGS_MAX = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULLPTR; - /* Arguments of yyformat: reported tokens (one for the "unexpected", - one per "expected"). */ - yysymbol_kind_t yyarg[YYARGS_MAX]; - /* Cumulated lengths of YYARG. */ - YYPTRDIFF_T yysize = 0; - - /* Actual size of YYARG. */ - int yycount = yy_syntax_error_arguments (yyctx, yyarg, YYARGS_MAX); - if (yycount == YYENOMEM) - return YYENOMEM; - - switch (yycount) - { -#define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - default: /* Avoid compiler warnings. */ - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -#undef YYCASE_ - } - - /* Compute error message size. Don't count the "%s"s, but reserve - room for the terminator. */ - yysize = yystrlen (yyformat) - 2 * yycount + 1; - { - int yyi; - for (yyi = 0; yyi < yycount; ++yyi) - { - YYPTRDIFF_T yysize1 - = yysize + yystrlen (yysymbol_name (yyarg[yyi])); - if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) - yysize = yysize1; - else - return YYENOMEM; - } - } - - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return -1; - } - - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp = yystpcpy (yyp, yysymbol_name (yyarg[yyi++])); - yyformat += 2; - } - else - { - ++yyp; - ++yyformat; - } - } - return 0; -} - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -static void -yydestruct (const char *yymsg, - yysymbol_kind_t yykind, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, char const *file_name) -{ - YY_USE (yyvaluep); - YY_USE (yylocationp); - YY_USE (file_name); - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YY_USE (yykind); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - -/* Lookahead token kind. */ -int yychar; - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; -/* Location data for the lookahead symbol. */ -YYLTYPE yylloc -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL - = { 1, 1, 1, 1 } -# endif -; -/* Number of syntax errors so far. */ -int yynerrs; - - - - -/*----------. -| yyparse. | -`----------*/ - -int -yyparse (char const *file_name) -{ - yy_state_fast_t yystate = 0; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus = 0; - - /* Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* Their size. */ - YYPTRDIFF_T yystacksize = YYINITDEPTH; - - /* The state stack: array, bottom, top. */ - yy_state_t yyssa[YYINITDEPTH]; - yy_state_t *yyss = yyssa; - yy_state_t *yyssp = yyss; - - /* The semantic value stack: array, bottom, top. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp = yyvs; - - /* The location stack: array, bottom, top. */ - YYLTYPE yylsa[YYINITDEPTH]; - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp = yyls; - - yy_state_t yyesa[20]; - yy_state_t *yyes = yyesa; - YYPTRDIFF_T yyes_capacity = 20 < YYMAXDEPTH ? 20 : YYMAXDEPTH; - - /* Whether LAC context is established. A Boolean. */ - int yy_lac_established = 0; - int yyn; - /* The return value of yyparse. */ - int yyresult; - /* Lookahead symbol kind. */ - yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - YYLTYPE yyloc; - - /* The locations where the error started and ended. */ - YYLTYPE yyerror_range[3]; - - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf; - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yychar = YYEMPTY; /* Cause a token to be read. */ - - yylsp[0] = yylloc; - goto yysetstate; - - -/*------------------------------------------------------------. -| yynewstate -- push a new state, which is found in yystate. | -`------------------------------------------------------------*/ -yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - -/*--------------------------------------------------------------------. -| yysetstate -- set current state (the top of the stack) to yystate. | -`--------------------------------------------------------------------*/ -yysetstate: - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - YY_ASSERT (0 <= yystate && yystate < YYNSTATES); - YY_IGNORE_USELESS_CAST_BEGIN - *yyssp = YY_CAST (yy_state_t, yystate); - YY_IGNORE_USELESS_CAST_END - YY_STACK_PRINT (yyss, yyssp); - - if (yyss + yystacksize - 1 <= yyssp) -#if !defined yyoverflow && !defined YYSTACK_RELOCATE - YYNOMEM; -#else - { - /* Get the current used size of the three stacks, in elements. */ - YYPTRDIFF_T yysize = yyssp - yyss + 1; - -# if defined yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - yy_state_t *yyss1 = yyss; - YYSTYPE *yyvs1 = yyvs; - YYLTYPE *yyls1 = yyls; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * YYSIZEOF (*yyssp), - &yyvs1, yysize * YYSIZEOF (*yyvsp), - &yyls1, yysize * YYSIZEOF (*yylsp), - &yystacksize); - yyss = yyss1; - yyvs = yyvs1; - yyls = yyls1; - } -# else /* defined YYSTACK_RELOCATE */ - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - YYNOMEM; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yy_state_t *yyss1 = yyss; - union yyalloc *yyptr = - YY_CAST (union yyalloc *, - YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); - if (! yyptr) - YYNOMEM; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); - YYSTACK_RELOCATE (yyls_alloc, yyls); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - yylsp = yyls + yysize - 1; - - YY_IGNORE_USELESS_CAST_BEGIN - YYDPRINTF ((stderr, "Stack size increased to %ld\n", - YY_CAST (long, yystacksize))); - YY_IGNORE_USELESS_CAST_END - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } -#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token\n")); - yychar = yylex (); - } - - if (yychar <= YYEOF) - { - yychar = YYEOF; - yytoken = YYSYMBOL_YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else if (yychar == YYerror) - { - /* The scanner already issued an error message, process directly - to error recovery. But do not keep the error token as - lookahead, it is too special and may lead us to an endless - loop in error recovery. */ - yychar = YYUNDEF; - yytoken = YYSYMBOL_YYerror; - yyerror_range[1] = yylloc; - goto yyerrlab1; - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - { - YY_LAC_ESTABLISH; - goto yydefault; - } - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yytable_value_is_error (yyn)) - goto yyerrlab; - yyn = -yyn; - YY_LAC_ESTABLISH; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - *++yylsp = yylloc; - - /* Discard the shifted token. */ - yychar = YYEMPTY; - YY_LAC_DISCARD ("shift"); - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - '$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - /* Default location. */ - YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); - yyerror_range[1] = yyloc; - YY_REDUCE_PRINT (yyn); - { - int yychar_backup = yychar; - switch (yyn) - { - case 2: /* program: textSection dataSection stackSection ".end" */ -#line 176 "asm.y" - { setProgAST(ast_program((yyvsp[-3].text_section), (yyvsp[-2].data_section), (yyvsp[-1].stack_section))); } -#line 1925 "asm.tab.c" - break; - - case 3: /* textSection: ".text" entryPoint asmInstrs */ -#line 179 "asm.y" - { (yyval.text_section) = ast_text_section((yyvsp[-2].token),(yyvsp[-1].addr),(yyvsp[0].asm_instrs)); } -#line 1931 "asm.tab.c" - break; - - case 5: /* addr: label */ -#line 184 "asm.y" - { (yyval.addr) = ast_addr_label((yyvsp[0].ident)); } -#line 1937 "asm.tab.c" - break; - - case 6: /* addr: unsignednumsym */ -#line 185 "asm.y" - { (yyval.addr) = ast_entry_addr((yyvsp[0].unsignednum)); } -#line 1943 "asm.tab.c" - break; - - case 8: /* asmInstrs: asmInstr */ -#line 191 "asm.y" - { (yyval.asm_instrs) = ast_asm_instrs_singleton((yyvsp[0].asm_instr)); } -#line 1949 "asm.tab.c" - break; - - case 9: /* asmInstrs: asmInstrs asmInstr */ -#line 192 "asm.y" - { (yyval.asm_instrs) = ast_asm_instrs_add((yyvsp[-1].asm_instrs),(yyvsp[0].asm_instr)); } -#line 1955 "asm.tab.c" - break; - - case 10: /* asmInstr: labelOpt instr eolsym */ -#line 195 "asm.y" - { (yyval.asm_instr) = ast_asm_instr((yyvsp[-2].label_opt),(yyvsp[-1].instr)); } -#line 1961 "asm.tab.c" - break; - - case 11: /* labelOpt: label ":" */ -#line 197 "asm.y" - { (yyval.label_opt) = ast_label_opt_label((yyvsp[-1].ident)); } -#line 1967 "asm.tab.c" - break; - - case 12: /* labelOpt: empty */ -#line 198 "asm.y" - { (yyval.label_opt) = ast_label_opt_empty((yyvsp[0].empty)); } -#line 1973 "asm.tab.c" - break; - - case 13: /* empty: %empty */ -#line 201 "asm.y" - { (yyval.empty) = ast_empty(lexer_filename(), lexer_line()); } -#line 1979 "asm.tab.c" - break; - - case 29: /* noArgInstr: noArgOp */ -#line 212 "asm.y" - { (yyval.instr) = ast_0arg_instr((yyvsp[0].token)); } -#line 1985 "asm.tab.c" - break; - - case 32: /* twoRegCompInstr: twoRegCompOp regsym "," offset "," regsym "," offset */ -#line 218 "asm.y" - { - (yyval.instr) = ast_2reg_instr((yyvsp[-7].token), (yyvsp[-6].reg).number, (yyvsp[-4].number).value, - (yyvsp[-2].reg).number, (yyvsp[0].number).value, - lexer_token2func((yyvsp[-7].token).toknum)); - } -#line 1995 "asm.tab.c" - break; - - case 43: /* offset: number */ -#line 230 "asm.y" - { - machine_types_check_fits_in_offset((yyvsp[0].number).value); - (yyval.number) = (yyvsp[0].number); - } -#line 2004 "asm.tab.c" - break; - - case 44: /* number: sign unsignednumsym */ -#line 237 "asm.y" - { - word_type val = (yyvsp[0].unsignednum).value; - if ((yyvsp[-1].token).toknum == minussym) { - val = - val; - } - (yyval.number) = ast_number((yyvsp[-1].token), val); - } -#line 2016 "asm.tab.c" - break; - - case 47: /* sign: empty */ -#line 247 "asm.y" - { (yyval.token) = ast_token(lexer_filename(), lexer_line(), plussym); } -#line 2022 "asm.tab.c" - break; - - case 48: /* twoRegNoOffsetsInstr: twoRegNoOffsetsOp regsym "," regsym */ -#line 252 "asm.y" - { - (yyval.instr) = ast_2reg_instr((yyvsp[-3].token), (yyvsp[-2].reg).number, 0, (yyvsp[0].reg).number, 0, - lexer_token2func((yyvsp[-3].token).toknum)); - } -#line 2031 "asm.tab.c" - break; - - case 50: /* noTargetOffsetInstr: noTargetOffsetOp regsym "," regsym "," offset */ -#line 262 "asm.y" - { - (yyval.instr) = ast_2reg_instr((yyvsp[-5].token), (yyvsp[-4].reg).number, 0, (yyvsp[-2].reg).number, (yyvsp[0].number).value, - lexer_token2func((yyvsp[-5].token).toknum)); - } -#line 2040 "asm.tab.c" - break; - - case 52: /* noSourceOffsetInstr: noSourceOffsetOp regsym "," offset "," regsym */ -#line 272 "asm.y" - { - (yyval.instr) = ast_2reg_instr((yyvsp[-5].token), (yyvsp[-4].reg).number, (yyvsp[-2].number).value, (yyvsp[0].reg).number, 0, - lexer_token2func((yyvsp[-5].token).toknum)); - } -#line 2049 "asm.tab.c" - break; - - case 54: /* oneRegOffsetArgInstr: oneRegOffsetArgOp regsym "," offset "," arg */ -#line 282 "asm.y" - { - (yyval.instr) = ast_1reg_instr((yyvsp[-5].token), other_comp_instr_type, - 1, (yyvsp[-4].reg).number, (yyvsp[-2].number).value, - lexer_token2func((yyvsp[-5].token).toknum), - ast_immed_number((yyvsp[0].number).value)); - } -#line 2060 "asm.tab.c" - break; - - case 56: /* arg: number */ -#line 293 "asm.y" - { /* the number is signed */ - machine_types_check_fits_in_arg((yyvsp[0].number).value); - (yyval.number) = (yyvsp[0].number); - } -#line 2069 "asm.tab.c" - break; - - case 57: /* oneRegArgInstr: oneRegArgOp regsym "," arg */ -#line 301 "asm.y" - { - (yyval.instr) = ast_1reg_instr((yyvsp[-3].token), other_comp_instr_type, - 1, (yyvsp[-2].reg).number, 0, - lexer_token2func((yyvsp[-3].token).toknum), - ast_immed_number((yyvsp[0].number).value)); - } -#line 2080 "asm.tab.c" - break; - - case 60: /* oneRegOffsetInstr: oneRegOffsetOp regsym "," offset */ -#line 313 "asm.y" - { - (yyval.instr) = ast_1reg_instr((yyvsp[-3].token), other_comp_instr_type, - 1, (yyvsp[-2].reg).number, (yyvsp[0].number).value, - lexer_token2func((yyvsp[-3].token).toknum), - ast_immed_none()); - } -#line 2091 "asm.tab.c" - break; - - case 67: /* shiftInstr: shiftOp regsym "," offset "," shift */ -#line 325 "asm.y" - { - (yyval.instr) = ast_1reg_instr((yyvsp[-5].token), other_comp_instr_type, - 1, (yyvsp[-4].reg).number, (yyvsp[-2].number).value, - lexer_token2func((yyvsp[-5].token).toknum), - (yyvsp[0].immed)); - } -#line 2102 "asm.tab.c" - break; - - case 70: /* shift: unsignednumsym */ -#line 336 "asm.y" - { - machine_types_check_fits_in_shift((yyvsp[0].unsignednum).value); - (yyval.immed) = ast_immed_unsigned((yyvsp[0].unsignednum).value); - } -#line 2111 "asm.tab.c" - break; - - case 71: /* argOnlyInstr: argOnlyOp arg */ -#line 344 "asm.y" - { - (yyval.instr) = ast_1reg_instr((yyvsp[-1].token), other_comp_instr_type, - 0, 0, 0, lexer_token2func((yyvsp[-1].token).toknum), - ast_immed_number((yyvsp[0].number).value)); - } -#line 2121 "asm.tab.c" - break; - - case 73: /* immedArithInstr: immedArithOp regsym "," offset "," immed */ -#line 355 "asm.y" - { - (yyval.instr) = ast_1reg_instr((yyvsp[-5].token), immed_instr_type, - 1, (yyvsp[-4].reg).number, (yyvsp[-2].number).value, - 0, (yyvsp[0].immed)); - } -#line 2131 "asm.tab.c" - break; - - case 75: /* immed: number */ -#line 365 "asm.y" - { - machine_types_check_fits_in_immed((yyvsp[0].number).value); - (yyval.immed) = ast_immed_number((yyvsp[0].number).value); - } -#line 2140 "asm.tab.c" - break; - - case 76: /* immedBoolInstr: immedBoolOp regsym "," offset "," uimmed */ -#line 373 "asm.y" - { - (yyval.instr) = ast_1reg_instr((yyvsp[-5].token), immed_instr_type, - 1, (yyvsp[-4].reg).number, (yyvsp[-2].number).value, - 0, (yyvsp[0].immed)); - } -#line 2150 "asm.tab.c" - break; - - case 81: /* uimmed: unsignednumsym */ -#line 383 "asm.y" - { - machine_types_check_fits_in_uimmed((yyvsp[0].unsignednum).value); - (yyval.immed) = ast_immed_unsigned((yyvsp[0].unsignednum).value); - } -#line 2159 "asm.tab.c" - break; - - case 82: /* branchTestInstr: branchTestOp regsym "," offset "," immed */ -#line 391 "asm.y" - { - (yyval.instr) = ast_1reg_instr((yyvsp[-5].token), immed_instr_type, - 1, (yyvsp[-4].reg).number, (yyvsp[-2].number).value, - 0, (yyvsp[0].immed)); - } -#line 2169 "asm.tab.c" - break; - - case 89: /* jumpInstr: jumpOp addr */ -#line 402 "asm.y" - { - if ((yyvsp[0].addr).address_defined) { - machine_types_check_fits_in_addr((yyvsp[0].addr).addr); - } - (yyval.instr) = ast_1reg_instr((yyvsp[-1].token), jump_instr_type, - 0, 0, 0, - 0, ast_immed_addr((yyvsp[0].addr))); - } -#line 2182 "asm.tab.c" - break; - - case 95: /* offsetOnlySyscall: offsetOnlySyscallOp offset */ -#line 418 "asm.y" - { - (yyval.instr) = ast_1reg_instr((yyvsp[-1].token), syscall_instr_type, - 1, 0, (yyvsp[0].number).value, - SYS_F, ast_syscall_code_for((yyvsp[-1].token).toknum)); - } -#line 2192 "asm.tab.c" - break; - - case 97: /* regOffsetSyscall: regOffsetSyscallOp regsym "," offset */ -#line 429 "asm.y" - { - (yyval.instr) = ast_1reg_instr((yyvsp[-3].token), syscall_instr_type, - 1, (yyvsp[-2].reg).number, (yyvsp[0].number).value, - SYS_F, ast_syscall_code_for((yyvsp[-3].token).toknum)); - } -#line 2202 "asm.tab.c" - break; - - case 102: /* noArgSyscall: noArgSyscallOp */ -#line 440 "asm.y" - { - (yyval.instr) = ast_1reg_instr((yyvsp[0].token), syscall_instr_type, - 0, 0, 0, - SYS_F, ast_syscall_code_for((yyvsp[0].token).toknum)); - } -#line 2212 "asm.tab.c" - break; - - case 105: /* dataSection: ".data" staticStartAddr staticDecls */ -#line 452 "asm.y" - { (yyval.data_section) = ast_data_section((yyvsp[-2].token), (yyvsp[-1].unsignednum).value, (yyvsp[0].static_decls)); } -#line 2218 "asm.tab.c" - break; - - case 107: /* staticDecls: empty */ -#line 458 "asm.y" - { (yyval.static_decls) = ast_static_decls_empty((yyvsp[0].empty)); } -#line 2224 "asm.tab.c" - break; - - case 108: /* staticDecls: staticDecls staticDecl */ -#line 459 "asm.y" - { (yyval.static_decls) = ast_static_decls_add((yyvsp[-1].static_decls),(yyvsp[0].static_decl)); } -#line 2230 "asm.tab.c" - break; - - case 109: /* staticDecl: dataSize identsym initializerOpt eolsym */ -#line 463 "asm.y" - { (yyval.static_decl) = ast_static_decl((yyvsp[-3].data_size), (yyvsp[-2].ident), (yyvsp[-1].initializer)); } -#line 2236 "asm.tab.c" - break; - - case 110: /* dataSize: "WORD" */ -#line 465 "asm.y" - { (yyval.data_size) = ast_data_size((yyvsp[0].token), ds_word, 1); } -#line 2242 "asm.tab.c" - break; - - case 111: /* dataSize: "CHAR" */ -#line 466 "asm.y" - { (yyval.data_size) = ast_data_size((yyvsp[0].token), ds_char, 1); } -#line 2248 "asm.tab.c" - break; - - case 112: /* dataSize: "STRING" "[" unsignednumsym "]" */ -#line 468 "asm.y" - { (yyval.data_size) = ast_data_size((yyvsp[-3].token), ds_string, - /* declared size is in words! */ - (yyvsp[-1].unsignednum).value); } -#line 2256 "asm.tab.c" - break; - - case 113: /* initializerOpt: "=" number */ -#line 472 "asm.y" - { (yyval.initializer) = ast_initializer_number((yyvsp[-1].token), (yyvsp[0].number).value); } -#line 2262 "asm.tab.c" - break; - - case 114: /* initializerOpt: "=" charliteralsym */ -#line 474 "asm.y" - { (yyval.initializer) = ast_initializer_char((yyvsp[-1].token), (yyvsp[0].charlit).value); } -#line 2268 "asm.tab.c" - break; - - case 115: /* initializerOpt: "=" stringliteralsym */ -#line 476 "asm.y" - { (yyval.initializer) = ast_initializer_string((yyvsp[-1].token), (yyvsp[0].stringlit).pointer); } -#line 2274 "asm.tab.c" - break; - - case 116: /* initializerOpt: empty */ -#line 477 "asm.y" - { (yyval.initializer) = ast_initializer_empty((yyvsp[0].empty)); } -#line 2280 "asm.tab.c" - break; - - case 117: /* stackSection: ".stack" stackBottomAddr */ -#line 482 "asm.y" - { (yyval.stack_section) = ast_stack_section((yyvsp[-1].token), (yyvsp[0].unsignednum).value); } -#line 2286 "asm.tab.c" - break; - - -#line 2290 "asm.tab.c" - - default: break; - } - if (yychar_backup != yychar) - YY_LAC_DISCARD ("yychar change"); - } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - - *++yyvsp = yyval; - *++yylsp = yyloc; - - /* Now 'shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - { - const int yylhs = yyr1[yyn] - YYNTOKENS; - const int yyi = yypgoto[yylhs] + *yyssp; - yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp - ? yytable[yyi] - : yydefgoto[yylhs]); - } - - goto yynewstate; - - -/*--------------------------------------. -| yyerrlab -- here on detecting error. | -`--------------------------------------*/ -yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; - { - yypcontext_t yyctx - = {yyssp, yyesa, &yyes, &yyes_capacity, yytoken, &yylloc}; - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - if (yychar != YYEMPTY) - YY_LAC_ESTABLISH; - yysyntax_error_status = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx); - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == -1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = YY_CAST (char *, - YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc))); - if (yymsg) - { - yysyntax_error_status - = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx); - yymsgp = yymsg; - } - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = YYENOMEM; - } - } - yyerror (file_name, yymsgp); - if (yysyntax_error_status == YYENOMEM) - YYNOMEM; - } - } - - yyerror_range[1] = yylloc; - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval, &yylloc, file_name); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - /* Pacify compilers when the user code never invokes YYERROR and the - label yyerrorlab therefore never appears in user code. */ - if (0) - YYERROR; - ++yynerrs; - - /* Do not reclaim the symbols of the rule whose action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - /* Pop stack until we find a state that shifts the error token. */ - for (;;) - { - yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYSYMBOL_YYerror; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - yyerror_range[1] = *yylsp; - yydestruct ("Error: popping", - YY_ACCESSING_SYMBOL (yystate), yyvsp, yylsp, file_name); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - /* If the stack popping above didn't lose the initial context for the - current lookahead token, the shift below will for sure. */ - YY_LAC_DISCARD ("error recovery"); - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - yyerror_range[2] = yylloc; - ++yylsp; - YYLLOC_DEFAULT (*yylsp, yyerror_range, 2); - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturnlab; - - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturnlab; - - -/*-----------------------------------------------------------. -| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | -`-----------------------------------------------------------*/ -yyexhaustedlab: - yyerror (file_name, YY_("memory exhausted")); - yyresult = 2; - goto yyreturnlab; - - -/*----------------------------------------------------------. -| yyreturnlab -- parsing is finished, clean up and return. | -`----------------------------------------------------------*/ -yyreturnlab: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc, file_name); - } - /* Do not reclaim the symbols of the rule whose action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yylsp, file_name); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif - if (yyes != yyesa) - YYSTACK_FREE (yyes); - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - return yyresult; -} - -#line 486 "asm.y" - - -// Set the program's ast to be t -void setProgAST(ast_program_t t) { progast = t; } diff --git a/vm/asm.tab.h b/vm/asm.tab.h deleted file mode 100755 index 7c23c48..0000000 --- a/vm/asm.tab.h +++ /dev/null @@ -1,166 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.8.2. */ - -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, - Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, - especially those whose name start with YY_ or yy_. They are - private implementation details that can be changed or removed. */ - -#ifndef YY_YY_ASM_TAB_H_INCLUDED -# define YY_YY_ASM_TAB_H_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int yydebug; -#endif -/* "%code requires" blocks. */ -#line 7 "asm.y" - - - /* Including "ast.h" must be at the top, to define the AST type */ -#include "ast.h" -#include "machine_types.h" -#include "parser_types.h" -#include "lexer.h" -// #include "utilities.h" // only needed for debugging - - /* Report an error to the user on stderr */ -extern void yyerror(const char *filename, const char *msg); - -#line 62 "asm.tab.h" - -/* Token kinds. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - YYEMPTY = -2, - YYEOF = 0, /* "end of file" */ - YYerror = 256, /* error */ - YYUNDEF = 257, /* "invalid token" */ - eolsym = 258, /* eolsym */ - identsym = 259, /* identsym */ - unsignednumsym = 260, /* unsignednumsym */ - plussym = 261, /* "+" */ - minussym = 262, /* "-" */ - commasym = 263, /* "," */ - dottextsym = 264, /* ".text" */ - dotdatasym = 265, /* ".data" */ - dotstacksym = 266, /* ".stack" */ - dotendsym = 267, /* ".end" */ - colonsym = 268, /* ":" */ - lbracketsym = 269, /* "[" */ - rbracketsym = 270, /* "]" */ - equalsym = 271, /* "=" */ - noopsym = 272, /* "NOP" */ - addopsym = 273, /* "ADD" */ - subopsym = 274, /* "SUB" */ - cpwopsym = 275, /* "CPW" */ - cpropsym = 276, /* "CPR" */ - andopsym = 277, /* "AND" */ - boropsym = 278, /* "BOR" */ - noropsym = 279, /* "NOR" */ - xoropsym = 280, /* "XOR" */ - lwropsym = 281, /* "LWR" */ - swropsym = 282, /* "SWR" */ - scaopsym = 283, /* "SCA" */ - lwiopsym = 284, /* "LWI" */ - negopsym = 285, /* "NEG" */ - litopsym = 286, /* "LIT" */ - ariopsym = 287, /* "ARI" */ - sriopsym = 288, /* "SRI" */ - mulopsym = 289, /* "MUL" */ - divopsym = 290, /* "DIV" */ - cfhiopsym = 291, /* "CFHI" */ - cfloopsym = 292, /* "CFLO" */ - sllopsym = 293, /* "SLL" */ - srlopsym = 294, /* "SRL" */ - jmpopsym = 295, /* "JMP" */ - jrelopsym = 296, /* "JREL" */ - addiopsym = 297, /* "ADDI" */ - andiopsym = 298, /* "ANDI" */ - boriopsym = 299, /* "BORI" */ - noriopsym = 300, /* "NORI" */ - xoriopsym = 301, /* "XORI" */ - beqopsym = 302, /* "BEQ" */ - bgezopsym = 303, /* "BGEZ" */ - blezopsym = 304, /* "BLEZ" */ - bgtzopsym = 305, /* "BGTZ" */ - bltzopsym = 306, /* "BLTZ" */ - bneopsym = 307, /* "BNE" */ - csiopsym = 308, /* "CSI" */ - jmpaopsym = 309, /* "JMPA" */ - callopsym = 310, /* "CALL" */ - rtnopsym = 311, /* "RTN" */ - exitopsym = 312, /* "EXIT" */ - pstropsym = 313, /* "PSTR" */ - pintopsym = 314, /* "PINT" */ - pchopsym = 315, /* "PCH" */ - rchopsym = 316, /* "RCH" */ - straopsym = 317, /* "STRA" */ - notropsym = 318, /* "NOTR" */ - regsym = 319, /* regsym */ - wordsym = 320, /* "WORD" */ - charsym = 321, /* "CHAR" */ - stringsym = 322, /* "STRING" */ - charliteralsym = 323, /* charliteralsym */ - stringliteralsym = 324 /* stringliteralsym */ - }; - typedef enum yytokentype yytoken_kind_t; -#endif - -/* Value type. */ - -/* Location type. */ -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE YYLTYPE; -struct YYLTYPE -{ - int first_line; - int first_column; - int last_line; - int last_column; -}; -# define YYLTYPE_IS_DECLARED 1 -# define YYLTYPE_IS_TRIVIAL 1 -#endif - - -extern YYSTYPE yylval; -extern YYLTYPE yylloc; - -int yyparse (char const *file_name); - - -#endif /* !YY_YY_ASM_TAB_H_INCLUDED */ diff --git a/vm/asm.y b/vm/asm.y deleted file mode 100755 index f086d1d..0000000 --- a/vm/asm.y +++ /dev/null @@ -1,489 +0,0 @@ - /* $Id: asm.y,v 1.64 2024/11/10 14:34:25 leavens Exp $ */ - -%code top { -#include -} - -%code requires { - - /* Including "ast.h" must be at the top, to define the AST type */ -#include "ast.h" -#include "machine_types.h" -#include "parser_types.h" -#include "lexer.h" -// #include "utilities.h" // only needed for debugging - - /* Report an error to the user on stderr */ -extern void yyerror(const char *filename, const char *msg); -} - -%verbose -%define parse.lac full -%define parse.error detailed - -%parse-param { char const *file_name } - -%token eolsym -%token identsym -%token unsignednumsym -%token plussym "+" -%token minussym "-" -%token commasym "," -%token dottextsym ".text" -%token dotdatasym ".data" -%token dotstacksym ".stack" -%token dotendsym ".end" -%token colonsym ":" -%token lbracketsym "[" -%token rbracketsym "]" -%token equalsym "=" -%token noopsym "NOP" -%token addopsym "ADD" -%token subopsym "SUB" -%token cpwopsym "CPW" -%token cpropsym "CPR" -%token andopsym "AND" -%token boropsym "BOR" -%token noropsym "NOR" -%token xoropsym "XOR" -%token lwropsym "LWR" -%token swropsym "SWR" -%token scaopsym "SCA" -%token lwiopsym "LWI" -%token negopsym "NEG" -%token litopsym "LIT" -%token ariopsym "ARI" -%token sriopsym "SRI" -%token mulopsym "MUL" -%token divopsym "DIV" -%token cfhiopsym "CFHI" -%token cfloopsym "CFLO" -%token sllopsym "SLL" -%token srlopsym "SRL" -%token jmpopsym "JMP" -%token jrelopsym "JREL" -%token addiopsym "ADDI" -%token andiopsym "ANDI" -%token boriopsym "BORI" -%token noriopsym "NORI" -%token xoriopsym "XORI" -%token beqopsym "BEQ" -%token bgezopsym "BGEZ" -%token blezopsym "BLEZ" -%token bgtzopsym "BGTZ" -%token bltzopsym "BLTZ" -%token bneopsym "BNE" -%token csiopsym "CSI" -%token jmpaopsym "JMPA" -%token callopsym "CALL" -%token rtnopsym "RTN" -%token exitopsym "EXIT" -%token pstropsym "PSTR" -%token pintopsym "PINT" -%token pchopsym "PCH" -%token rchopsym "RCH" -%token straopsym "STRA" -%token notropsym "NOTR" - -%token regsym - -%token wordsym "WORD" -%token charsym "CHAR" -%token stringsym "STRING" -%token charliteralsym -%token stringliteralsym - - -%type program -%type textSection -%type entryPoint -%type addr -%type label -%type asmInstr -%type labelOpt -%type empty -%type asmInstrs -%type instr -%type noArgInstr -%type noArgOp -%type twoRegCompInstr -%type twoRegCompOp -%type offset -%type number -%type sign -%type twoRegNoOffsetsInstr -%type twoRegNoOffsetsOp -%type noTargetOffsetInstr -%type noTargetOffsetOp -%type noSourceOffsetInstr -%type noSourceOffsetOp -%type oneRegOffsetArgInstr -%type oneRegOffsetArgOp -%type oneRegArgInstr -%type oneRegArgOp -%type arg -%type oneRegOffsetInstr -%type oneRegOffsetOp -%type shiftInstr -%type shiftOp -%type shift -%type argOnlyInstr -%type argOnlyOp -%type immedArithInstr -%type immedArithOp -%type immed -%type immedBoolInstr -%type immedBoolOp -%type uimmed -%type branchTestInstr -%type branchTestOp -%type jumpInstr -%type jumpOp -%type syscallInstr -%type offsetOnlySyscall -%type offsetOnlySyscallOp -%type regOffsetSyscall -%type regOffsetSyscallOp -%type noArgSyscall -%type noArgSyscallOp -%type dataSection -%type staticStartAddr -%type staticDecls -%type staticDecl -%type dataSize -%type initializerOpt -%type stackSection -%type stackBottomAddr - -%start program - -%code { - /* extern declarations provided by the lexer */ -extern int yylex(void); - - /* extern void yyerror(char const *msg); */ - - /* The AST for the program, set by the semantic action for program. */ -ast_program_t progast; - - /* Set the program's ast to be t */ -extern void setProgAST(ast_program_t t); -} - -%% - -program : textSection dataSection stackSection ".end" - { setProgAST(ast_program($1, $2, $3)); } ; - -textSection : ".text" entryPoint asmInstrs - { $$ = ast_text_section($1,$2,$3); } ; - - -entryPoint : addr ; - -addr : label { $$ = ast_addr_label($1); } - | unsignednumsym { $$ = ast_entry_addr($1); } - ; - -label : identsym ; - - -asmInstrs : asmInstr { $$ = ast_asm_instrs_singleton($1); } - | asmInstrs asmInstr { $$ = ast_asm_instrs_add($1,$2); } - ; - -asmInstr : labelOpt instr eolsym { $$ = ast_asm_instr($1,$2); } ; - -labelOpt : label ":" { $$ = ast_label_opt_label($1); } - | empty { $$ = ast_label_opt_empty($1); } - ; - -empty : %empty { $$ = ast_empty(lexer_filename(), lexer_line()); } ; - - -instr : noArgInstr | twoRegCompInstr | twoRegNoOffsetsInstr - | noTargetOffsetInstr | noSourceOffsetInstr | oneRegOffsetArgInstr - | oneRegArgInstr | oneRegOffsetInstr | shiftInstr | argOnlyInstr - | immedArithInstr | immedBoolInstr | branchTestInstr | jumpInstr - | syscallInstr - ; - - -noArgInstr : noArgOp { $$ = ast_0arg_instr($1); } ; - -noArgOp : "NOP" | "RTN" ; - - -twoRegCompInstr : twoRegCompOp regsym "," offset "," regsym "," offset - { - $$ = ast_2reg_instr($1, $2.number, $4.value, - $6.number, $8.value, - lexer_token2func($1.toknum)); - } - ; - -twoRegCompOp : "ADD" | "SUB" | "CPW" - | "AND" | "BOR" | "NOR" | "XOR" | "SCA" | "LWI" | "NEG" ; - - -offset : number - { - machine_types_check_fits_in_offset($1.value); - $$ = $1; - } - ; - -number : sign unsignednumsym - { - word_type val = $2.value; - if ($1.toknum == minussym) { - val = - val; - } - $$ = ast_number($1, val); - } - ; - -sign : "+" | "-" - | empty { $$ = ast_token(lexer_filename(), lexer_line(), plussym); } - ; - - -twoRegNoOffsetsInstr : twoRegNoOffsetsOp regsym "," regsym - { - $$ = ast_2reg_instr($1, $2.number, 0, $4.number, 0, - lexer_token2func($1.toknum)); - } - ; - -twoRegNoOffsetsOp : "CPR" ; - - -noTargetOffsetInstr : noTargetOffsetOp regsym "," regsym "," offset - { - $$ = ast_2reg_instr($1, $2.number, 0, $4.number, $6.value, - lexer_token2func($1.toknum)); - } - ; - -noTargetOffsetOp : "LWR" ; - - -noSourceOffsetInstr : noSourceOffsetOp regsym "," offset "," regsym - { - $$ = ast_2reg_instr($1, $2.number, $4.value, $6.number, 0, - lexer_token2func($1.toknum)); - } - ; - -noSourceOffsetOp : "SWR" ; - - -oneRegOffsetArgInstr : oneRegOffsetArgOp regsym "," offset "," arg - { - $$ = ast_1reg_instr($1, other_comp_instr_type, - 1, $2.number, $4.value, - lexer_token2func($1.toknum), - ast_immed_number($6.value)); - } - ; - -oneRegOffsetArgOp : "LIT" ; - -arg : number - { /* the number is signed */ - machine_types_check_fits_in_arg($1.value); - $$ = $1; - } - ; - - -oneRegArgInstr : oneRegArgOp regsym "," arg - { - $$ = ast_1reg_instr($1, other_comp_instr_type, - 1, $2.number, 0, - lexer_token2func($1.toknum), - ast_immed_number($4.value)); - } - ; - -oneRegArgOp : "ARI" | "SRI" ; - - -oneRegOffsetInstr : oneRegOffsetOp regsym "," offset - { - $$ = ast_1reg_instr($1, other_comp_instr_type, - 1, $2.number, $4.value, - lexer_token2func($1.toknum), - ast_immed_none()); - } - ; - -oneRegOffsetOp : "MUL" | "DIV" | "CFHI" | "CFLO" | "JMP" | "CSI" ; - - -shiftInstr : shiftOp regsym "," offset "," shift - { - $$ = ast_1reg_instr($1, other_comp_instr_type, - 1, $2.number, $4.value, - lexer_token2func($1.toknum), - $6); - } - ; - -shiftOp : "SLL" | "SRL" ; - -shift : unsignednumsym - { - machine_types_check_fits_in_shift($1.value); - $$ = ast_immed_unsigned($1.value); - } - ; - - -argOnlyInstr : argOnlyOp arg - { - $$ = ast_1reg_instr($1, other_comp_instr_type, - 0, 0, 0, lexer_token2func($1.toknum), - ast_immed_number($2.value)); - } - ; - -argOnlyOp : "JREL" ; - - -immedArithInstr : immedArithOp regsym "," offset "," immed - { - $$ = ast_1reg_instr($1, immed_instr_type, - 1, $2.number, $4.value, - 0, $6); - } - ; - -immedArithOp : "ADDI" ; - -immed : number - { - machine_types_check_fits_in_immed($1.value); - $$ = ast_immed_number($1.value); - } - ; - - -immedBoolInstr : immedBoolOp regsym "," offset "," uimmed - { - $$ = ast_1reg_instr($1, immed_instr_type, - 1, $2.number, $4.value, - 0, $6); - } - ; - -immedBoolOp : "ANDI" | "BORI" | "XORI" | "NORI" ; - -uimmed : unsignednumsym - { - machine_types_check_fits_in_uimmed($1.value); - $$ = ast_immed_unsigned($1.value); - } - ; - - -branchTestInstr : branchTestOp regsym "," offset "," immed - { - $$ = ast_1reg_instr($1, immed_instr_type, - 1, $2.number, $4.value, - 0, $6); - } - ; - -branchTestOp : "BEQ" | "BGEZ" | "BGTZ" | "BLEZ" | "BLTZ" | "BNE" ; - - -jumpInstr : jumpOp addr - { - if ($2.address_defined) { - machine_types_check_fits_in_addr($2.addr); - } - $$ = ast_1reg_instr($1, jump_instr_type, - 0, 0, 0, - 0, ast_immed_addr($2)); - } - ; - -jumpOp : "JMPA" | "CALL" ; - - -syscallInstr : offsetOnlySyscall | regOffsetSyscall | noArgSyscall - -offsetOnlySyscall : offsetOnlySyscallOp offset - { - $$ = ast_1reg_instr($1, syscall_instr_type, - 1, 0, $2.value, - SYS_F, ast_syscall_code_for($1.toknum)); - } - ; - -offsetOnlySyscallOp : "EXIT" ; - - -regOffsetSyscall : regOffsetSyscallOp regsym "," offset - { - $$ = ast_1reg_instr($1, syscall_instr_type, - 1, $2.number, $4.value, - SYS_F, ast_syscall_code_for($1.toknum)); - } - ; - -regOffsetSyscallOp : "PSTR" | "PINT" | "PCH" | "RCH" ; - - -noArgSyscall : noArgSyscallOp - { - $$ = ast_1reg_instr($1, syscall_instr_type, - 0, 0, 0, - SYS_F, ast_syscall_code_for($1.toknum)); - } - ; - -noArgSyscallOp : "STRA" | "NOTR" ; - - - -dataSection : ".data" staticStartAddr staticDecls - { $$ = ast_data_section($1, $2.value, $3); } - ; - -staticStartAddr : unsignednumsym ; - - -staticDecls : empty { $$ = ast_static_decls_empty($1); } - | staticDecls staticDecl { $$ = ast_static_decls_add($1,$2); } - ; - -staticDecl : dataSize identsym initializerOpt eolsym - { $$ = ast_static_decl($1, $2, $3); } ; - -dataSize : "WORD" { $$ = ast_data_size($1, ds_word, 1); } - | "CHAR" { $$ = ast_data_size($1, ds_char, 1); } - | "STRING" "[" unsignednumsym "]" - { $$ = ast_data_size($1, ds_string, - /* declared size is in words! */ - $3.value); } ; - -initializerOpt : "=" number { $$ = ast_initializer_number($1, $2.value); } - | "=" charliteralsym - { $$ = ast_initializer_char($1, $2.value); } - | "=" stringliteralsym - { $$ = ast_initializer_string($1, $2.pointer); } - | empty { $$ = ast_initializer_empty($1); } - ; - - -stackSection : ".stack" stackBottomAddr - { $$ = ast_stack_section($1, $2.value); } ; - -stackBottomAddr : unsignednumsym ; - -%% - -// Set the program's ast to be t -void setProgAST(ast_program_t t) { progast = t; } diff --git a/vm/asm_lexer.l b/vm/asm_lexer.l deleted file mode 100755 index 94f0051..0000000 --- a/vm/asm_lexer.l +++ /dev/null @@ -1,379 +0,0 @@ -/* $Id: asm_lexer.l,v 1.59 2024/11/10 14:34:25 leavens Exp $ */ -/* Scanner for the SSM Assembly Language */ - -%option header-file = "asm_lexer.h" -%option outfile = "asm_lexer.c" -%option yylineno -%option bison-bridge - -%{ -#include -#include -#include -#include "ast.h" -#include "parser_types.h" -#include "utilities.h" -#include "char_utilities.h" -#include "lexer.h" - - /* Tokens generated by Bison */ -#include "asm.tab.h" - - /* need declaration of fileno, part of the C standard library. - (Putting an extern declaration here shuts off a gcc warning.) */ -extern int fileno(FILE *stream); - -/* The filename of the file being read */ -char *filename; - -/* Have any errors been noted? */ -bool errors_noted; - -/* The value of a token */ -extern YYSTYPE yylval; - -/* The FILE used by the generated lexer */ -extern FILE *yyin; - -#undef yywrap /* sometimes a macro by default */ - -// apparently strdup is not declared in -extern char *strdup(const char *s); - -// set the lexer's value for a token in yylval as an AST -static void tok2ast(int toknum) { - AST t; - t.token.file_loc = file_location_make(filename, yylineno); - t.token.type_tag = token_ast; - t.token.toknum = toknum; - t.token.text = strdup(yytext); - yylval = t; -} - -static void reg2ast(const char *txt) { - AST t; - t.reg.file_loc = file_location_make(filename, yylineno); - t.reg.type_tag = reg_ast; - t.reg.text = strdup(yytext); - reg_num_type n; - sscanf(txt, "%hu", &n); - t.reg.number = n; - yylval = t; -} - -static void namedreg2ast(unsigned short num, const char *txt) { - AST t; - t.reg.file_loc = file_location_make(filename, yylineno); - t.reg.type_tag = reg_ast; - t.reg.text = strdup(yytext); - t.reg.number = num; - yylval = t; -} - - -static void ident2ast(const char *name) { - AST t; - t.ident.file_loc = file_location_make(filename, yylineno); - t.ident.type_tag = ident_ast; - t.ident.name = strdup(name); - yylval = t; -} - -static void unsignednum2ast(unsigned int val) -{ - AST t; - t.unsignednum.file_loc = file_location_make(filename, yylineno); - t.unsignednum.type_tag = unsignednum_ast; - t.unsignednum.text = strdup(yytext); - t.unsignednum.value = val; - yylval = t; -} - -static void charliteral2ast() -{ - AST t; - int charlit_len; // number of characters in the literal - t.charlit.file_loc = file_location_make(filename, yylineno); - assert(t.charlit.file_loc != NULL); - t.charlit.type_tag = char_literal_ast; - const char *start_of_literal = yytext+1; - t.charlit.value = char_utilities_char_value(start_of_literal, - &charlit_len); - yylval = t; -} - -#define STRINGLITERALMAXSIZE 1024 - -static void stringliteral2ast() -{ - AST t; - t.stringlit.file_loc = file_location_make(filename, yylineno); - assert(t.stringlit.file_loc != NULL); - t.stringlit.type_tag = string_literal_ast; - int len = strlen(yytext); - if (len < 2) { - bail_with_error("String literal is too short in stringLiteral2ast!"); - } - assert(len >= 2); - // take off length for the quotation marks, - len = len - 2; - - char strval[STRINGLITERALMAXSIZE]; - int ri = 0; // result index (into strval) - int yi = 1; // index into yytext - int charlit_len = 0; // length read for a char literal - while (yi <= len && yytext[yi] != '\"' && ri < (STRINGLITERALMAXSIZE-1)) { - strval[ri] = char_utilities_char_value(yytext+yi, &charlit_len); - ri++; - yi = yi+charlit_len; - } - if (ri >= STRINGLITERALMAXSIZE) { - bail_with_prog_error(*(t.stringlit.file_loc), - "String literal is too long (missing double quote?)"); - } - strval[ri] = '\0'; - assert(ri == strlen(strval)); - t.stringlit.pointer = strdup(strval); - yylval = t; -} - -%} - - /* you can add actual definitions below */ - -DECDIGIT [0-9] -OCTDIGIT [0-7] -HEXDIGIT [0-9A-Fa-f] -UNSIGNEDNUMBER (((0x){HEXDIGIT}+)|{DECDIGIT}+) -LETTER [_a-zA-Z] -LETTERORDIGIT ({LETTER}|{DECDIGIT}) -IDENT {LETTER}({LETTERORDIGIT}*) -NEWLINE \n -CR \r -EOL ({NEWLINE}|({CR}{NEWLINE})) -COMMENTSTART # -COMMENT {COMMENTSTART}.* -IGNORED [ \t\v\f\r] -BACKSLASH \\ -CHARAFTERBACKSLASH ([nrftvab'\"\\]|x{HEXDIGIT}+|0{OCTDIGIT}*) -CHARESCAPE {BACKSLASH}{CHARAFTERBACKSLASH} - /* char codes for char-literals */ -CHARCODE ({CHARESCAPE}|[^\'\\\n]) - /* string chars for string-literals */ -STRINGCHAR ({CHARESCAPE}|[^\"\\\n]) - - /* states of the lexer */ - -%s INSTRUCTION -%s DATADECL - -%% - -{IGNORED} { ; } /* do nothing */ -{COMMENT} { ; } /* ignore comments */ -{EOL} { BEGIN INITIAL; return eolsym; } -{EOL} { BEGIN INITIAL; return eolsym; } -{EOL} { ; } /* ignore EOL outside of the above states */ - -NOP { BEGIN INSTRUCTION; tok2ast(noopsym); return noopsym; } -ADD { BEGIN INSTRUCTION; tok2ast(addopsym); return addopsym; } -SUB { BEGIN INSTRUCTION; tok2ast(subopsym); return subopsym; } -CPW { BEGIN INSTRUCTION; tok2ast(cpwopsym); return cpwopsym; } -CPR { BEGIN INSTRUCTION; tok2ast(cpropsym); return cpropsym; } -AND { BEGIN INSTRUCTION; tok2ast(andopsym); return andopsym; } -BOR { BEGIN INSTRUCTION; tok2ast(boropsym); return boropsym; } -NOR { BEGIN INSTRUCTION; tok2ast(noropsym); return noropsym; } -XOR { BEGIN INSTRUCTION; tok2ast(xoropsym); return xoropsym; } -LWR { BEGIN INSTRUCTION; tok2ast(lwropsym); return lwropsym; } -SWR { BEGIN INSTRUCTION; tok2ast(swropsym); return swropsym; } -SCA { BEGIN INSTRUCTION; tok2ast(scaopsym); return scaopsym; } -LWI { BEGIN INSTRUCTION; tok2ast(lwiopsym); return lwiopsym; } -NEG { BEGIN INSTRUCTION; tok2ast(negopsym); return negopsym; } -LIT { BEGIN INSTRUCTION; tok2ast(litopsym); return litopsym; } -ARI { BEGIN INSTRUCTION; tok2ast(ariopsym); return ariopsym; } -SRI { BEGIN INSTRUCTION; tok2ast(sriopsym); return sriopsym; } -MUL { BEGIN INSTRUCTION; tok2ast(mulopsym); return mulopsym; } -DIV { BEGIN INSTRUCTION; tok2ast(divopsym); return divopsym; } -CFHI { BEGIN INSTRUCTION; tok2ast(cfhiopsym); return cfhiopsym; } -CFLO { BEGIN INSTRUCTION; tok2ast(cfloopsym); return cfloopsym; } -SLL { BEGIN INSTRUCTION; tok2ast(sllopsym); return sllopsym; } -SRL { BEGIN INSTRUCTION; tok2ast(srlopsym); return srlopsym; } -JMP { BEGIN INSTRUCTION; tok2ast(jmpopsym); return jmpopsym; } -CSI { BEGIN INSTRUCTION; tok2ast(csiopsym); return csiopsym; } -JREL { BEGIN INSTRUCTION; tok2ast(jrelopsym); return jrelopsym; } -ADDI { BEGIN INSTRUCTION; tok2ast(addiopsym); return addiopsym; } -ANDI { BEGIN INSTRUCTION; tok2ast(andiopsym); return andiopsym; } -BORI { BEGIN INSTRUCTION; tok2ast(boriopsym); return boriopsym; } -NORI { BEGIN INSTRUCTION; tok2ast(xoriopsym); return noriopsym; } -XORI { BEGIN INSTRUCTION; tok2ast(xoriopsym); return xoriopsym; } -BEQ { BEGIN INSTRUCTION; tok2ast(beqopsym); return beqopsym; } -BGEZ { BEGIN INSTRUCTION; tok2ast(bgezopsym); return bgezopsym; } -BGTZ { BEGIN INSTRUCTION; tok2ast(bgtzopsym); return bgtzopsym; } -BLEZ { BEGIN INSTRUCTION; tok2ast(blezopsym); return blezopsym; } -BLTZ { BEGIN INSTRUCTION; tok2ast(bltzopsym); return bltzopsym; } -BNE { BEGIN INSTRUCTION; tok2ast(bneopsym); return bneopsym; } -JMPA { BEGIN INSTRUCTION; tok2ast(jmpaopsym); return jmpaopsym; } -CALL { BEGIN INSTRUCTION; tok2ast(callopsym); return callopsym; } -RTN { BEGIN INSTRUCTION; tok2ast(rtnopsym); return rtnopsym; } -EXIT { BEGIN INSTRUCTION; tok2ast(exitopsym); return exitopsym; } -PSTR { BEGIN INSTRUCTION; tok2ast(pstropsym); return pstropsym; } -PINT { BEGIN INSTRUCTION; tok2ast(pintopsym); return pintopsym; } -PCH { BEGIN INSTRUCTION; tok2ast(pchopsym); return pchopsym; } -RCH { BEGIN INSTRUCTION; tok2ast(rchopsym); return rchopsym; } -STRA { BEGIN INSTRUCTION; tok2ast(straopsym); return straopsym; } -NOTR { BEGIN INSTRUCTION; tok2ast(notropsym); return notropsym; } - -WORD { BEGIN DATADECL; tok2ast(wordsym); return wordsym; } -CHAR { BEGIN DATADECL; tok2ast(charsym); return charsym; } -STRING { BEGIN DATADECL; tok2ast(stringsym); return stringsym; } - -\+ { tok2ast(plussym); return plussym; } -- { tok2ast(minussym); return minussym; } -, { return commasym; } - -\.text { tok2ast(dottextsym); return dottextsym; } -\.data { tok2ast(dotdatasym); return dotdatasym; } -\.stack { tok2ast(dotstacksym); return dotstacksym; } -\.end { return dotendsym; } -\= { tok2ast(equalsym); return equalsym; } -: { return colonsym; } -\[ { tok2ast(lbracketsym); return lbracketsym; } -\] { tok2ast(rbracketsym); return rbracketsym; } - -'{CHARCODE}' { charliteral2ast(); return charliteralsym; } -\"{STRINGCHAR}*\" { stringliteral2ast(); return stringliteralsym; } - -{UNSIGNEDNUMBER} { unsigned int val; - int ssf_ret; - size_t len = strlen(yytext); - if (yyleng >= 2 && (strncmp(yytext, "0x", 2) == 0)) { - // hex literal - if (len > 8+2) { - bail_with_error( - "Unsigned literal has too many digits \"%s\"", - yytext); - } - ssf_ret = sscanf(yytext+2, "%x", &val); - if (ssf_ret != 1) { - bail_with_error("Unsigned hex literal (%s) could not be read by lexer!", - yytext); - } - } else { - if (len > 10) { // 2^32 has 10 digits - bail_with_error( - "Unsigned decimal literal has too many digits \"%s\"", - yytext); - } - ssf_ret = sscanf(yytext, "%du", &val); - if (ssf_ret != 1) { - bail_with_error("Unsigned decimal literal (%s) could not be read by lexer!", - yytext); - } - } - unsignednum2ast(val); - return unsignednumsym; - } - -${OCTDIGIT} { reg2ast(yytext+1); return regsym; } -${UNSIGNEDNUMBER} { char msgbuf[512]; - sprintf(msgbuf, "Register numbers must be between 0 and 7 (inclusive, (not like \"%s\")", - yytext); - yyerror(lexer_filename(), msgbuf); - } -$gp { namedreg2ast(0,yytext); return regsym; } -$sp { namedreg2ast(1,yytext); return regsym; } -$fp { namedreg2ast(2,yytext); return regsym; } -$r3 { namedreg2ast(3,yytext); return regsym; } -$r4 { namedreg2ast(4,yytext); return regsym; } -$r5 { namedreg2ast(5,yytext); return regsym; } -$r6 { namedreg2ast(6,yytext); return regsym; } -$ra { namedreg2ast(7,yytext); return regsym; } -{IDENT} { ident2ast(yytext); return identsym; } - - -. { char msgbuf[512]; - sprintf(msgbuf, "invalid character: '%c' ('\\0%o')", *yytext, *yytext); - yyerror(lexer_filename(), msgbuf); - } -%% - -/* Requires: fname != NULL - * Requires: fname is the name of a readable file - * Initialize the lexer and start it reading from the given file. */ -void lexer_init(char *fname) { - errors_noted = false; - filename = fname; - yyin = fopen(fname, "r"); - if (yyin == NULL) { - bail_with_error("Lexer cannot open %s", fname); - } -} - -// Close the file yyin -// and return 1 to indicate that there are no more files -int yywrap() { - if (yyin != NULL) { - int rc = fclose(yyin); - if (rc == EOF) { - bail_with_error("Cannot close %s!", filename); - } - } - filename = NULL; - return 1; /* no more input */ -} - -// Return the name of the current input file -const char *lexer_filename() { - return filename; -} - -// Return the line number of the next token -unsigned int lexer_line() { - return yylineno; -} - -/* Report an error to the user on stderr */ -void yyerror(const char *filename, const char *msg) -{ - fflush(stdout); - fprintf(stderr, "%s:%d: %s\n", filename, lexer_line(), msg); - errors_noted = true; -} - -// On standard output: -// Print a message about the file name of the lexer's input -// and then print a heading for the lexer's output. -void lexer_print_output_header() -{ - printf("Tokens from file %s\n", lexer_filename()); - printf("%-6s %-4s %s\n", "Number", "Line", "Text"); -} - -// Print information about the token t to stdout -// followed by a newline -void lexer_print_token(enum yytokentype t, unsigned int tline, - const char *txt) -{ - printf("%-6d %-4d \"%s\"\n", t, tline, txt); -} - -/* Read all the tokens from the input file - * and print each token on standard output - * using the format in lexer_print_token */ -void lexer_output() -{ - lexer_print_output_header(); - AST dummy; - yytoken_kind_t t; - do { - t = yylex(&dummy); - if (t == YYEOF) { - break; - } - if (t != eolsym) { - lexer_print_token(t, yylineno, yytext); - } else { - lexer_print_token(t, yylineno, "\\n"); - } - } while (t != YYEOF); -} diff --git a/vm/asm_main.c b/vm/asm_main.c deleted file mode 100755 index be189f2..0000000 --- a/vm/asm_main.c +++ /dev/null @@ -1,148 +0,0 @@ -/* $Id: asm_main.c,v 1.20 2024/07/16 14:11:23 leavens Exp $ */ -#include -#include -#include -#include "ast.h" -#include "parser_types.h" -#include "bof.h" -#include "lexer.h" -#include "asm.tab.h" -#include "instruction.h" -#include "utilities.h" -#include "asm_unparser.h" -#include "pass1.h" -#include "assemble.h" - -// strdup seems to be in the string library but not in the header... -extern char *strdup(const char *s); - -/* The program's AST, set by the parser */ -extern ast_program_t progast; - -// Requires: fn is a name that ends in .asm -// Modify fn to have the extension .bof -static void change_to_bof_ext(char *fn) { - int len = strlen(fn); - if (len <= 3) { - bail_with_error("Not enough chars in file name passed to chage_to_bof_ext (\"%s\")", - fn); - } - // assert(len > 3); - char *endstr = strrchr(fn, '.'); - // assert(*endstr == '.'); - if (strcmp(endstr, ".asm") != 0) { - bail_with_error("Name passed to change_to_bof_ext does not end in .asm (\"%s\")", - fn); - } - strcpy(endstr, ".bof"); -} - -char * cmdname; -static const char *typicalFile = "file.asm"; - -void usage() { - bail_with_error("Usage: %s %s\n %s %s %s\n %s %s %s\n %s %s %s", - cmdname, typicalFile, - cmdname, "-l", typicalFile, - cmdname, "-u", typicalFile, - cmdname, "-s", typicalFile); - exit(EXIT_FAILURE); -} - -extern int yydebug; - -int main(int argc, char *argv[]) { - // should the tokens seen by the lexer be printed? - bool lexer_print_output = false; - // should the unparse be printed? - bool parser_unparse = false; - // should the symbol table be printed after pass 1? - bool symbol_table_print = false; - - cmdname = argv[0]; - argc--; - argv++; - - // possible options: -l, -u, and -s - while (argc > 0 && strlen(argv[0]) >= 2 && argv[0][0] == '-') { - if (strcmp(argv[0],"-l") == 0) { - lexer_print_output = true; - argc--; - argv++; - } else if (strcmp(argv[0],"-u") == 0) { - parser_unparse = true; - argc--; - argv++; - } else if (strcmp(argv[0],"-s") == 0) { - symbol_table_print = true; - argc--; - argv++; - } else { - // bad option! - usage(); - } - } - - // give usage message if -l and other options are used - if ( lexer_print_output && (symbol_table_print || parser_unparse) ) { - usage(); - } - - // give usage message if -u and other options are used - if ( parser_unparse && symbol_table_print ) { - usage(); - } - - // must have a file name - if (argc <= 0 || (strlen(argv[0]) >= 2 && argv[0][0] == '-')) { - usage(); - } - - // the name of the file - char *file_name = argv[0]; - - if (lexer_print_output) { - // with the lexer_print_output option, nothing else is done - lexer_init(file_name); - lexer_output(); - if (errors_noted) { - return EXIT_FAILURE; - } else { - return EXIT_SUCCESS; - } - } - - // otherwise (if not lexer_print_outout) continue to parse etc. - lexer_init(file_name); - int parser_ret = yyparse(file_name); - if (parser_ret != 0) { - exit(EXIT_FAILURE); - } - - if (parser_unparse) { - unparseProgram(stdout, progast); - } - - if (parser_unparse) { - return EXIT_SUCCESS; - } - - // check for duplicate declarations of labels/names and build symbol table - pass1(progast); - - // print debugging information about the symbol table - if (symbol_table_print) { - pass1_print(stdout); - } - - char *bfn = strdup(file_name); - change_to_bof_ext(bfn); - - BOFFILE bf = bof_write_open(bfn); - - // generate code from the ASTs - assembleProgram(bf, progast); - bof_close(bf); - - return EXIT_SUCCESS; -} diff --git a/vm/asm_unparser.c b/vm/asm_unparser.c deleted file mode 100755 index 3af6c51..0000000 --- a/vm/asm_unparser.c +++ /dev/null @@ -1,268 +0,0 @@ -/* $Id: asm_unparser.c,v 1.30 2024/08/28 21:25:00 leavens Exp $ */ -#include -#include -#include -#include "ast.h" -#include "utilities.h" -#include "char_utilities.h" -#include "regname.h" -#include "asm_unparser.h" - -// Note: newlines and indentation are only printed -// by a function which deals with a grammar that sensibly needs one printed, -// as this makes them those functions more reusable. - -// Unparse prog, with output going to the file out -void unparseProgram(FILE *out, ast_program_t prog) -{ - unparseTextSection(out, prog.textSection); - unparseDataSection(out, prog.dataSection); - unparseStackSection(out, prog.stackSection); - fprintf(out, ".end"); - newline(out); -} - -// Unparse the given AST, with output going to out -void unparseTextSection(FILE *out, ast_text_section_t ts) -{ - fprintf(out, ".text "); - unparseEntryPoint(out, ts.entryPoint); - newline(out); - unparseAsmInstrs(out, ts.instrs); -} - -// Unparse the given AST, with output going to out -void unparseEntryPoint(FILE *out, ast_addr_t ep) -{ - unparseAddr(out, ep); -} - -// Unparse the given AST, with output going to out -void unparseAddr(FILE *out, ast_addr_t addr) -{ - if (addr.label != NULL) { - fprintf(out, "%s", addr.label); - } else { - fprintf(out, "%u", addr.addr); - } -} - -// Unparse the given AST, with output going to out -void unparseAsmInstrs(FILE *out, ast_asm_instrs_t instrs) -{ - ast_asm_instr_t *ip = instrs.instrs; - while (ip != NULL) { - unparseAsmInstr(out, *ip); - ip = ip->next; - } -} - -// Unparse the given AST, with output going to out -void unparseAsmInstr(FILE *out, ast_asm_instr_t instr) -{ - unparseLabelOpt(out, instr.label_opt); - unparseInstr(out, instr.instr); - newline(out); -} - -// Unparse the given AST, with output going to out -void unparseLabelOpt(FILE *out, ast_label_opt_t lopt) -{ - if (lopt.name == NULL) { - fprintf(out, "\t"); - } else { - fprintf(out, "%s:\t", lopt.name); - } -} - -// Unparse the given AST, with output going to out -void unparseInstr(FILE *out, ast_instr_t instr) -{ - fprintf(out, "%s ", instr.opname); - - // print any registers used - switch (instr.opcode) { - case COMP_O: - switch (instr.func) { - case NOP_F: - // no arguments, so nothing to print! - break; - case LWR_F: - fprintf(out, "%s, %s, %hd", - unparseReg(instr.reg), unparseReg(instr.reg2), - instr.offset2); - break; - case SWR_F: - fprintf(out, "%s, %hd, %s", - unparseReg(instr.reg), instr.offset, - unparseReg(instr.reg2)); - break; - default: // all the rest of these instructions - fprintf(out, "%s, %hd, %s, %hd", - unparseReg(instr.reg), instr.offset, - unparseReg(instr.reg2), instr.offset2); - break; - } - break; - case OTHC_O: - switch (instr.func) { - case LIT_F: - fprintf(out, "%s, %hd, %hd", - unparseReg(instr.reg), instr.offset, - instr.immed_data.data.immed); - break; - case ARI_F: case SRI_F: case MUL_F: case DIV_F: - case CFHI_F: case CFLO_F: case JMP_F: case CSI_F: - fprintf(out, "%s, %hd", - unparseReg(instr.reg), instr.offset); - break; - case SLL_F: case SRL_F: - fprintf(out, "%s, %hd, %hu", - unparseReg(instr.reg), instr.offset, - instr.immed_data.data.uimmed); - break; - case JREL_F: - fprintf(out, "%hd", instr.immed_data.data.immed); - break; - case SYS_F: - switch (instr.immed_data.data.syscall_code) { - case exit_sc: - fprintf(out, "%hd", instr.offset); - break; - case print_str_sc: case print_char_sc: case read_char_sc: - fprintf(out, "%s, %hd", unparseReg(instr.reg), instr.offset); - break; - case start_tracing_sc: case stop_tracing_sc: - // no arguments! - break; - default: - bail_with_error("Unknown syscall_code in SYS_F case of unparseInstr!"); - break; - } - break; - default: - bail_with_error("Unknown other computational opcode in unparseInstr %d", instr.opcode); - break; - } - break; - case ADDI_O: - fprintf(out, "%s, %hd, %hd", - unparseReg(instr.reg), instr.offset, instr.immed_data.data.immed); - break; - case ANDI_O: case BORI_O: case NORI_O: case XORI_O: - fprintf(out, "%s, %hd, %hx", - unparseReg(instr.reg), instr.offset, instr.immed_data.data.uimmed); - break; - case BEQ_O: case BGEZ_O: case BGTZ_O: case BLEZ_O: case BLTZ_O: case BNE_O: - fprintf(out, "%s, %hd, %hd", - unparseReg(instr.reg), instr.offset, instr.immed_data.data.immed); - break; - case JMPA_O: case CALL_O: - unparseImmediateAddress(out, instr.immed_data.data.addr); - break; - case RTN_O: - // no arguments, so nothing to print! - break; - default: - bail_with_error("Unknown opcode (%d) in unparseInstr!", instr.opcode); - break; - } -} - -// Unparse the given AST, with output going to out -void unparseImmediateAddress(FILE *out, ast_addr_t addr) -{ - if (addr.address_defined) { - fprintf(out, "%u", addr.addr); - } else { - fprintf(out, "%s", addr.label); - } -} - -// Unparse a register, returning a string for the register's name -const char *unparseReg(reg_num_type n) -{ - if (0 <= n && n < NUM_REGISTERS) { - return regname_get(n); - } else { - bail_with_error("Bad register number (%d)!", n); - return NULL; // never happens - } -} - -// Unparse the given AST, with output going to out -void unparseDataSection(FILE *out, ast_data_section_t ds) -{ - fprintf(out, ".data %u", ds.static_start_addr); - newline(out); - unparseStaticDecls(out, ds.staticDecls); -} - -// Unparse the given AST, with output going to out -void unparseStaticDecls(FILE *out, ast_static_decls_t sds) -{ - ast_static_decl_t *dcl = sds.decls; - while (dcl != NULL) { - unparseStaticDecl(out, *dcl); - dcl = dcl->next; - } -} - -// Unparse the given AST, with output going to out -void unparseStaticDecl(FILE *out, ast_static_decl_t dcl) -{ - unparseDataSize(out, dcl); - fprintf(out, "\t"); - unparseIdent(out, dcl.ident); - fprintf(out, " "); - unparseInitializer(out, dcl.initializer); - newline(out); -} - -// Unparse the data size declaration, with output going to out -void unparseDataSize(FILE *out, ast_static_decl_t dcl) -{ - fprintf(out, "%s ", dcl.size_name); - if (dcl.dse == ds_string) { - fprintf(out, "[%u]", dcl.size_in_words); - } -} - -// Unparse the given AST, with output going to out -void unparseIdent(FILE *out, ast_ident_t id) -{ - fprintf(out, "%s", id.name); -} - - -// Unparse the given AST, with output going to out -void unparseInitializer(FILE *out, ast_initializer_opt_t init) -{ - switch (init.kind) { - case initzlr_k_number: - fprintf(out, "= %d", init.num_value); - break; - case initzlr_k_char: - fprintf(out, "= '%s'", char_utilities_unescape_char(init.num_value)); - break; - case initzlr_k_string: - fprintf(out, "= \""); - fprintf(out, "%s", char_utilities_unescape_string(init.str_value)); - fprintf(out, "\""); - break; - case initzlr_k_none: - // don't print anything! - break; - default: - bail_with_error("Unknown initializer kind in unparseInitializer!"); - break; - } -} - - -// Unparse the given AST, with output going to out -void unparseStackSection(FILE *out, ast_stack_section_t ss) -{ - fprintf(out, ".stack %u", ss.stack_bottom_addr); - newline(out); -} diff --git a/vm/asm_unparser.h b/vm/asm_unparser.h deleted file mode 100755 index 931b096..0000000 --- a/vm/asm_unparser.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $Id: asm_unparser.h,v 1.9 2024/07/29 16:17:19 leavens Exp $ */ -#ifndef _ASM_UNPARSER_H -#define _ASM_UNPARSER_H -#include -#include "ast.h" - -// Unparse prog, with output going to the file out -extern void unparseProgram(FILE *out, ast_program_t prog); - -// Unparse the given AST, with output going to out -extern void unparseTextSection(FILE *out, ast_text_section_t ts); - -// Unparse the given AST, with output going to out -extern void unparseEntryPoint(FILE *out, ast_addr_t ep); - -// Unparse the given AST, with output going to out -extern void unparseAddr(FILE *out, ast_addr_t l); - -// Unparse the given AST, with output going to out -extern void unparseAsmInstrs(FILE *out, ast_asm_instrs_t instrs); - -// Unparse the given AST, with output going to out -extern void unparseAsmInstr(FILE *out, ast_asm_instr_t instr); - -// Unparse the given AST, with output going to out -extern void unparseLabelOpt(FILE *out, ast_label_opt_t lopt); - -// Unparse the given AST, with output going to out -extern void unparseInstr(FILE *out, ast_instr_t instr); - -// Unparse the given AST, with output going to out -extern void unparseImmediateAddress(FILE *out, ast_addr_t addr); - -// Unparse a register, returning a string for the register's name -extern const char *unparseReg(reg_num_type n); - -// Unparse the given AST, with output going to out -extern void unparseDataSection(FILE *out, ast_data_section_t ds); - -// Unparse the given AST, with output going to out -extern void unparseStaticDecls(FILE *out, ast_static_decls_t sds); - -// Unparse the given AST, with output going to out -extern void unparseStaticDecl(FILE *out, ast_static_decl_t dcl); - -// Unparse the data size declartion, with output going to out -void unparseDataSize(FILE *out, ast_static_decl_t dcl); - -// Unparse the given AST, with output going to out -extern void unparseIdent(FILE *out, ast_ident_t id); - -// Unparse the given AST, with output going to out -extern void unparseInitializer(FILE *out, ast_initializer_opt_t init); - -// Unparse the given AST, with output going to out -extern void unparseStackSection(FILE *out, ast_stack_section_t ss); - -#endif diff --git a/vm/assemble.c b/vm/assemble.c deleted file mode 100755 index d99ec94..0000000 --- a/vm/assemble.c +++ /dev/null @@ -1,236 +0,0 @@ -/* $Id: assemble.c,v 1.36 2024/08/29 21:58:39 leavens Exp $ */ -#include -#include -#include -#include "ast.h" -#include "utilities.h" -#include "assemble.h" -#include "bof.h" -#include "symtab.h" -#include "id_attrs_assoc.h" -#include "regname.h" - -// Return the address associated with the addr l -static address_type addr2address(ast_addr_t addr) -{ - address_type ret = addr.addr; - if (addr.address_defined) { - return ret; - } else { - // the address is not defined yet - id_attrs_assoc *ida = symtab_lookup(addr.label); - if (ida == NULL) { - bail_with_prog_error(*(addr.file_loc), - "Label \"%s\" was never defined!", - addr.label); - } - return ida->addr; - } -} - -// Assemble the code for prog, with output going to bf -void assembleProgram(BOFFILE bf, ast_program_t prog) -{ - BOFHeader bh; - bof_write_magic_to_header(&bh); - bh.text_start_address = addr2address(prog.textSection.entryPoint); - bh.text_length = ast_list_length(prog.textSection.instrs.instrs); - bh.data_start_address = prog.dataSection.static_start_addr; - // have to write the header first, so need to know the true size - // of the data section before writing the header - bh.data_length = assemble_dataSection_words(prog.dataSection); - bh.stack_bottom_addr = prog.stackSection.stack_bottom_addr; - bof_write_header(bf, bh); - assembleTextSection(bf, prog.textSection); - assembleDataSection(bf, prog.dataSection); - // nothing to do for the stack section, as it's all in the header -} - -// Assemble the code for the given AST, with output going to bf -void assembleTextSection(BOFFILE bf, ast_text_section_t ts) -{ - assembleAsmInstrs(bf, ts.instrs); -} - -// Assemble the code for the given AST, with output going to bf -void assembleAsmInstrs(BOFFILE bf, ast_asm_instrs_t instrs) -{ - ast_asm_instr_t *ip = instrs.instrs; - while (ip != NULL) { - assembleAsmInstr(bf, *ip); - ip = ip->next; - } -} - -// Assemble the code for the given AST, with output going to bf -void assembleAsmInstr(BOFFILE bf, ast_asm_instr_t instr) -{ - assembleInstr(bf, instr.instr); -} - -// Return the value of the immedidate data AST immed -static unsigned int immedData_value(ast_immedData_t immed) -{ - int ret = 0; - switch (immed.id_data_kind) { - case id_number: - ret = immed.data.immed; - break; - case id_syscall_code: - ret = immed.data.syscall_code; - break; - case id_unsigned: - ret = immed.data.uimmed; - break; - case id_addr: - return addr2address(immed.data.addr); - break; - case id_empty: - ret = 0; - break; - default: - bail_with_error("Unknown immed_data_kind_t (%d) in immedData_value", - immed.id_data_kind); - break; - } - return ret; -} - -// Assemble the code for the given AST, with output going to bf -void assembleInstr(BOFFILE bf, ast_instr_t instr) -{ - switch (instr.itype) { - case comp_instr_type: - comp_instr_t ci; - ci.op = instr.opcode; - assert(ci.op == COMP_O); - ci.rt = instr.reg; - ci.ot = instr.offset; - ci.rs = instr.reg2; - ci.os = instr.offset2; - ci.func = instr.func; - instruction_write_compInstr(bf, ci); - break; - case other_comp_instr_type: - other_comp_instr_t oci; - oci.op = instr.opcode; - assert(oci.op == OTHC_O); - oci.reg = instr.reg; - oci.offset = instr.offset; - oci.arg = instr.immed_data.data.uimmed; - oci.func = instr.func; - instruction_write_otherCompInstr(bf, oci); - break; - case syscall_instr_type: - syscall_instr_t si; - si.op = OTHC_O; - si.reg = instr.reg; - si.offset = instr.offset; - si.code = (syscall_type) immedData_value(instr.immed_data); - si.func = SYS_F; - instruction_write_syscallInstr(bf, si); - break; - case immed_instr_type: - switch (instr.opcode) { - case ANDI_O: case BORI_O: case NORI_O: case XORI_O: - uimmed_instr_t ui; - ui.op = instr.opcode; - ui.reg = instr.reg; - ui.offset = instr.offset; - ui.uimmed = immedData_value(instr.immed_data); - instruction_write_uimmedInstr(bf, ui); - break; - default: - immed_instr_t ii; - ii.op = instr.opcode; - ii.reg = instr.reg; - ii.offset = instr.offset; - ii.immed = (immediate_type) immedData_value(instr.immed_data); - instruction_write_immedInstr(bf, ii); - break; - } - break; - case jump_instr_type: - jump_instr_t ji; - ji.op = instr.opcode; - ji.addr = (address_type) immedData_value(instr.immed_data); - instruction_write_jumpInstr(bf, ji); - break; - default: - bail_with_error("Bad instr_type in assembleInstr (%d)!", instr.itype); - break; - } -} - -// return the size (in words) of the data section's declarations -unsigned int assemble_dataSection_words(ast_data_section_t ds) -{ - return assemble_staticDecls_words(ds.staticDecls); -} - -// return the size (in words) of the given static declarations -unsigned int assemble_staticDecls_words(ast_static_decls_t sds) -{ - int ret = 0; - ast_static_decl_t *dcl = sds.decls; - while (dcl != NULL) { - ret += assemble_staticDecl_words(*dcl); - dcl = dcl->next; - } - return ret; -} - -// return the size (in words) of the given static declarations -unsigned int assemble_staticDecl_words(ast_static_decl_t sd) -{ - return sd.size_in_words; -} - -// Assemble the code for the given AST, with output going to bf -void assembleDataSection(BOFFILE bf, ast_data_section_t ds) -{ - assembleStaticDecls(bf, ds.staticDecls); -} - -// Assemble the code for the given AST, with output going to bf -void assembleStaticDecls(BOFFILE bf, ast_static_decls_t sds) -{ - ast_static_decl_t *dcl = sds.decls; - while (dcl != NULL) { - assembleStaticDecl(bf, *dcl); - dcl = dcl->next; - } -} - -// Assemble the code for the given AST, with output going to bf -void assembleStaticDecl(BOFFILE bf, ast_static_decl_t dcl) -{ - switch (dcl.initializer.kind) { - case initzlr_k_number: case initzlr_k_char: - bof_write_word(bf, dcl.initializer.num_value); - break; - case initzlr_k_string: - bof_write_bytes(bf, dcl.initializer.byte_size, - dcl.initializer.str_value); - // pad to word-align the space for the string - int padding_needed = ((dcl.size_in_words * BYTES_PER_WORD) - - dcl.initializer.byte_size); - assert(padding_needed >= 0); - assert(((dcl.initializer.byte_size + padding_needed) - % BYTES_PER_WORD) == 0); - int zeros[2] = {0, 0}; - for (int i = 0; i < padding_needed; i++) { - bof_write_bytes(bf, 1, zeros); - } - break; - case initzlr_k_none: - for (int i = 0; i < (dcl.size_in_words); i++) { - bof_write_word(bf, 0); - } - break; - default: - bail_with_error("Unknown declaration kind (%d) in assembleStaticDecl!", - dcl.initializer.kind); - break; - } -} diff --git a/vm/assemble.h b/vm/assemble.h deleted file mode 100755 index dd3c67d..0000000 --- a/vm/assemble.h +++ /dev/null @@ -1,41 +0,0 @@ -/* $Id: assemble.h,v 1.10 2024/07/28 22:01:51 leavens Exp $ */ -#ifndef _ASSEMBLE_H -#define _ASSEMBLE_H -#include -#include "ast.h" -#include "bof.h" - -// Generate code for prog, with output going to bf -extern void assembleProgram(BOFFILE bf, ast_program_t prog); - -// Generate code for the given AST, with output going to bf -extern void assembleTextSection(BOFFILE bf, ast_text_section_t ts); - -// Generate code for the given AST, with output going to bf -extern void assembleAsmInstrs(BOFFILE bf, ast_asm_instrs_t instrs); - -// Generate code for the given AST, with output going to bf -extern void assembleAsmInstr(BOFFILE bf, ast_asm_instr_t instr); - -// Generate code for the given AST, with output going to bf -extern void assembleInstr(BOFFILE bf, ast_instr_t instr); - -// return the size (in words) of the data section's declarations -extern unsigned int assemble_dataSection_words(ast_data_section_t ds); - -// return the size (in words) of the given static declarations -extern unsigned int assemble_staticDecls_words(ast_static_decls_t sds); - -// return the size (in words) of the given static declaration -extern unsigned int assemble_staticDecl_words(ast_static_decl_t sd); - -// Generate code for the given AST, with output going to bf -extern void assembleDataSection(BOFFILE bf, ast_data_section_t ds); - -// Generate code for the given AST, with output going to bf -extern void assembleStaticDecls(BOFFILE bf, ast_static_decls_t sds); - -// Generate code for the given AST, with output going to bf -extern void assembleStaticDecl(BOFFILE bf, ast_static_decl_t dcl); - -#endif diff --git a/vm/ast.c b/vm/ast.c deleted file mode 100755 index 34d482d..0000000 --- a/vm/ast.c +++ /dev/null @@ -1,547 +0,0 @@ -/* $Id: ast.c,v 1.44 2024/08/29 00:06:21 leavens Exp $ */ -#include -#include -#include "utilities.h" -#include "ast.h" -#include "lexer.h" - -// Return (a pointer to) the file location from an AST -const file_location *ast_file_loc(AST t) { - return t.generic.file_loc; -} - -// Return the filename from the AST t -const char *ast_filename(AST t) { - return ast_file_loc(t)->filename; -} - -// Return the line number from the AST t -unsigned int ast_line(AST t) { - return ast_file_loc(t)->line; -} - -// Return the type tag of the AST t -AST_type ast_type_tag(AST t) { - return t.generic.type_tag; -} - -// Return an AST for a program, -// which contains the given ASTs. -ast_program_t ast_program(ast_text_section_t textSec, - ast_data_section_t dataSec, - ast_stack_section_t stackSec) -{ - ast_program_t ret; - ret.file_loc = textSec.file_loc; - ret.type_tag = program_ast; - ret.textSection = textSec; - ret.dataSection = dataSec; - ret.stackSection = stackSec; - return ret; -} - -// Return an AST for the text section -// with the given entry point and instructions. -ast_text_section_t ast_text_section(ast_token_t tok, ast_addr_t entryPoint, - ast_asm_instrs_t instrs) -{ - ast_text_section_t ret; - ret.file_loc = file_location_copy(tok.file_loc); - ret.type_tag = text_section_ast; - ret.entryPoint = entryPoint; - ret.instrs = instrs; - return ret; -} - -// Return an AST for an entry point -// that represents the label given -ast_addr_t ast_addr_label(ast_ident_t label) -{ - ast_addr_t ret; - ret.file_loc = file_location_copy(label.file_loc); - ret.type_tag = addr_ast; - ret.address_defined = false; - ret.label = label.name; - ret.addr = 0; - return ret; -} - -// Return an AST for an entry point -// that represents the address given -ast_addr_t ast_entry_addr(ast_unsignednum_t addr) -{ - ast_addr_t ret; - ret.file_loc = file_location_copy(addr.file_loc); - ret.type_tag = addr_ast; - ret.address_defined = true; - ret.label = NULL; - ret.addr = addr.value; - return ret; -} - -// Return an AST for an asm instr AST -// with the given label-opt and instruction -ast_asm_instr_t ast_asm_instr(ast_label_opt_t labelOpt, ast_instr_t instr) -{ - ast_asm_instr_t ret; - ret.file_loc = labelOpt.file_loc; - ret.type_tag = asm_instr_ast; - ret.next = NULL; - ret.label_opt = labelOpt; - ret.instr = instr; - return ret; -} - -// Return an AST for a singleton asm instrs AST -// with the given instruction -ast_asm_instrs_t ast_asm_instrs_singleton(ast_asm_instr_t asminstr) -{ - ast_asm_instrs_t ret; - ret.file_loc = asminstr.file_loc; - ret.type_tag = asm_instrs_ast; - ast_asm_instr_t *p = (ast_asm_instr_t *)malloc(sizeof(ast_asm_instr_t)); - if (p == NULL) { - bail_with_error("Cannot allocate space for an asm_instr!"); - } - *p = asminstr; - p->next = NULL; - ret.instrs = p; - return ret; -} - -// Return an AST made from adding instr to the end of lst -ast_asm_instrs_t ast_asm_instrs_add(ast_asm_instrs_t lst, ast_asm_instr_t asminstr) -{ - ast_asm_instrs_t ret = lst; - ast_asm_instr_t *p = (ast_asm_instr_t *)malloc(sizeof(ast_asm_instr_t)); - if (p == NULL) { - bail_with_error("Cannot allocate space for an asm_instr!"); - } - *p = asminstr; - p->next = NULL; - // splice p onto the end of lst.instrs - ast_asm_instr_t *last = ast_last_list_elem(lst.instrs); - if (last == NULL) { - ret.instrs = p; - } else { - last->next = p; - } - return ret; -} - -// Requires: id.name != NULL. -// Return an AST for a label_opt AST -// with the given identifier -ast_label_opt_t ast_label_opt_label(ast_ident_t id) -{ - ast_label_opt_t ret; - ret.file_loc = file_location_copy(id.file_loc); - ret.type_tag = label_opt_ast; - ret.name = id.name; - return ret; -} - -// Return an AST for a label_opt AST -// with the empty AST (t) -ast_label_opt_t ast_label_opt_empty(ast_empty_t t) -{ - ast_label_opt_t ret; - ret.file_loc = file_location_copy(t.file_loc); - ret.type_tag = label_opt_ast; - ret.name = NULL; - return ret; -} - -// Return an immediate data holding a number -ast_immedData_t ast_immed_number(word_type n) { - ast_immedData_t ret; - ret.id_data_kind = id_number; - ret.data.immed = n; - return ret; -} - -// Return an immediate data holding an unsigned int -ast_immedData_t ast_immed_unsigned(unsigned int u) { - ast_immedData_t ret; - ret.id_data_kind = id_unsigned; - ret.data.uimmed = u; - return ret; -} - -// Requires: toknum is the token number of a system call operation. -// Return an immedidate data holding a system call code for t -extern ast_immedData_t ast_syscall_code_for(int toknum) -{ - ast_immedData_t ret; - ret.id_data_kind = id_syscall_code; - ret.data.syscall_code - = (syscall_type) instruction_token2SyscallCode(toknum); - return ret; -} - -// Return an immediate data holding an address -ast_immedData_t ast_immed_addr(ast_addr_t a) { - ast_immedData_t ret; - ret.id_data_kind = id_addr; - ret.data.addr = a; - return ret; -} - -// Return an immediate data that is nothing -ast_immedData_t ast_immed_none() { - ast_immedData_t ret; - ret.id_data_kind = id_empty; - return ret; -} - -// Return an instruction AST for a (no-argument) instruction -ast_instr_t ast_0arg_instr(ast_token_t op) -{ - ast_instr_t ret; - ret.file_loc = file_location_copy(op.file_loc); - ret.type_tag = instr_ast; - ret.next = NULL; - ret.opname = op.text; - ret.opcode = lexer_token2opcode(op.toknum); - assert(op.toknum != noopsym || ret.opcode == COMP_O); - if (ret.opcode == COMP_O) { - ret.itype = comp_instr_type; - ret.func = lexer_token2func(op.toknum); - } else if (ret.opcode == OTHC_O) { - ret.itype = other_comp_instr_type; - ret.func = lexer_token2func(op.toknum); - } else { - // the func code is not used with other instruction types - ret.itype = jump_instr_type; - ret.func = 0; - } - ret.regs_used = 0; - ret.reg = 0; // not really needed - ret.offset = 0; // not really needed - ret.reg2 = 0; // not really needed - ret.offset2 = 0; // not really needed - ret.immed_data = ast_immed_none(); - return ret; -} - -// Return an instruction AST -// for a (2-register) computational instruction -ast_instr_t ast_2reg_instr(ast_token_t op, - unsigned short rt, offset_type ot, - unsigned short rs, offset_type os, - func_type func) -{ - ast_instr_t ret; - ret.file_loc = file_location_copy(op.file_loc); - ret.type_tag = instr_ast; - ret.next = NULL; - ret.itype = comp_instr_type; // only this type has 2 registers & 2 offsets - ret.opname = op.text; - ret.opcode = lexer_token2opcode(op.toknum); - ret.func = func; - ret.regs_used = 2; - ret.reg = rt; - ret.offset = ot; - ret.reg2 = rs; - ret.offset2 = os; - ret.immed_data = ast_immed_none(); - return ret; -} - -// Return an AST for an instruction -// with the given information -ast_instr_t ast_1reg_instr(ast_token_t op, instr_type itype, - unsigned short num_regs_used, - unsigned short reg, offset_type offset, - func_type func, ast_immedData_t im) -{ - ast_instr_t ret; - ret.file_loc = file_location_copy(op.file_loc); - ret.type_tag = instr_ast; - ret.next = NULL; - ret.itype = itype; - ret.opname = op.text; - ret.opcode = lexer_token2opcode(op.toknum); - ret.func = func; - ret.regs_used = num_regs_used; - switch (num_regs_used) { - case 0: - ret.reg = 0; - ret.offset = 0; - break; - case 1: - ret.reg = reg; - ret.offset = offset; - break; - default: - bail_with_error("ast_1reg_instr called with unknown number of registers!"); - break; - } - ret.immed_data = im; - ret.reg2 = 0; // reg2 is not used - ret.offset2 = 0; // offset2 is not used - return ret; -} - -// Return an AST for the data section AST -// with the given list of static declarations. -ast_data_section_t ast_data_section(ast_token_t kw, unsigned int static_start, - ast_static_decls_t staticDecls) -{ - ast_data_section_t ret; - ret.file_loc = file_location_copy(kw.file_loc); - ret.type_tag = data_section_ast; - ret.static_start_addr = static_start; - ret.staticDecls = staticDecls; - return ret; -} - -// Return an AST for an empty list of static decls -ast_static_decls_t ast_static_decls_empty(ast_empty_t e) -{ - ast_static_decls_t ret; - ret.file_loc = file_location_copy(e.file_loc); - ret.type_tag = static_decls_ast; - ret.decls = NULL; - return ret; -} - -// Return an AST for a list of static declarations -// with sd added to the end of sds -ast_static_decls_t ast_static_decls_add(ast_static_decls_t sds, - ast_static_decl_t sd) -{ - ast_static_decls_t ret = sds; - ast_static_decl_t *p = (ast_static_decl_t *)malloc(sizeof(ast_static_decl_t)); - if (p == NULL) { - bail_with_error("Cannot allocate space for a static_decl!"); - } - *p = sd; - p->next = NULL; - // splice p onto the end of sds.decls - ast_static_decl_t *last = ast_last_list_elem(sds.decls); - if (last == NULL) { - ret.decls = p; - } else { - last->next = p; - } - return ret; -} - -// Return an AST for a data size delclarator -// for the given number of words -ast_data_size_t ast_data_size(ast_token_t kw, data_size_e dse, - unsigned short words) -{ - extern char *strdup(const char *s); - ast_data_size_t ret; - ret.file_loc = file_location_copy(kw.file_loc); - ret.type_tag = data_size_ast; - ret.dse = dse; - ret.size_name = strdup(kw.text); - ret.size_in_words = words; - return ret; -} - -// Requires: init.byte_size <= (ds.size_in_words * BYTES_PER_WORD). -// Return an AST for a static declaration -// with the given data size, identifier, and initializer. -// Note that the size is taken from the ds argument, not the initializer. -ast_static_decl_t ast_static_decl(ast_data_size_t ds, - ast_ident_t ident, - ast_initializer_opt_t init) -{ - ast_static_decl_t ret; - ret.file_loc = file_location_copy(ds.file_loc); - ret.type_tag = static_decl_ast; - ret.next = NULL; - ret.size_in_words = ds.size_in_words; - if (init.kind != initzlr_k_none) { - // give an error if the declared size and initializer don't match - // TODO: move these checks to a static checking pass - if (init.byte_size > (ds.size_in_words * BYTES_PER_WORD)) { - // assert(init.file_loc != NULL); - fprintf(stderr, "Initializer size (%u bytes) is too big for declared data size (%u bytes)!\n", - init.byte_size, (ds.size_in_words * BYTES_PER_WORD)); - if (init.str_value != NULL) { - fprintf(stderr, "Note: initializer string is %s\n", init.str_value); - } - } - } - ret.dse = ds.dse; - switch (ds.dse) { - case ds_word: - if (init.kind == initzlr_k_string) { - bail_with_prog_error(*(init.file_loc), - "Using a string initializer for word data!"); - } - break; - case ds_char: - if (init.kind == initzlr_k_string) { - bail_with_prog_error(*(init.file_loc), - "Using a string initializer for char data!"); - } else if (init.kind == initzlr_k_number) { - bail_with_prog_error(*(init.file_loc), - "Using a word initializer for char data!"); - } - break; - case ds_string: - if (init.kind != initzlr_k_string) { - bail_with_prog_error(*(init.file_loc), - "String data requires a string initializer!"); - } - break; - } - ret.size_name = ds.size_name; - ret.ident = ident; - ret.initializer = init; - return ret; -} - -// Return an AST for an initializer with the given number -ast_initializer_opt_t ast_initializer_number(ast_token_t eqs, - word_type value) -{ - ast_initializer_opt_t ret; - ret.file_loc = file_location_copy(eqs.file_loc); - ret.type_tag = initializer_opt_ast; - ret.kind = initzlr_k_number; - ret.byte_size = BYTES_PER_WORD; - ret.num_value = value; - return ret; -} - -// Return an AST for an initializer with the given char literal -ast_initializer_opt_t ast_initializer_char(ast_token_t eqs, - char c) -{ - ast_initializer_opt_t ret; - ret.file_loc = file_location_copy(eqs.file_loc); - ret.type_tag = initializer_opt_ast; - ret.kind = initzlr_k_char; - ret.byte_size = BYTES_PER_WORD; // make it word aligned - ret.num_value = c; - return ret; -} - -// Return an AST for an initializer with the given string literal -ast_initializer_opt_t ast_initializer_string(ast_token_t eqs, - const char *s) -{ - ast_initializer_opt_t ret; - ret.file_loc = file_location_copy(eqs.file_loc); - ret.type_tag = initializer_opt_ast; - ret.kind = initzlr_k_string; - ret.byte_size = strlen(s) + 1; // add 1 for null char at end - ret.str_value = s; - return ret; -} - - -// Return an AST for an empty initializer -ast_initializer_opt_t ast_initializer_empty(ast_empty_t e) -{ - ast_initializer_opt_t ret; - ret.file_loc = file_location_copy(e.file_loc); - ret.type_tag = initializer_opt_ast; - ret.kind = initzlr_k_none; - // the other fields should not be used when the kind is as above - return ret; -} - -// Return an AST for empty found in the file named fn, on line ln -ast_empty_t ast_empty(const char *fn, unsigned int ln) -{ - ast_empty_t ret; - ret.file_loc = file_location_make(fn, ln); - ret.type_tag = empty_ast; - return ret; -} - -// Return an AST for a stack section AST -// with the given keyword and stack bottom address. -ast_stack_section_t ast_stack_section(ast_token_t kw, - unsigned int stack_bottom) -{ - ast_stack_section_t ret; - ret.file_loc = file_location_copy(kw.file_loc); - ret.type_tag = stack_section_ast; - ret.stack_bottom_addr = stack_bottom; - return ret; -} - -// Return an AST for an identifier -// found in the file named fn, on line ln, with the given name. -ast_ident_t ast_ident(const char *fn, unsigned int ln, const char *name) -{ - ast_ident_t ret; - ret.file_loc = file_location_make(fn, ln); - ret.type_tag = ident_ast; - ret.name = name; - return ret; -} - -// Return an AST for a (signed) number with the given value -ast_number_t ast_number(ast_token_t sgn, word_type value) -{ - ast_number_t ret; - ret.file_loc = file_location_copy(sgn.file_loc); - ret.type_tag = number_ast; - ret.value = value; - return ret; -} - -// Return an AST for an (unsigned) number -// with the given value -ast_unsignednum_t ast_unsignednum(const char *fn, unsigned int ln, - unsigned int value) -{ - ast_unsignednum_t ret; - ret.file_loc = file_location_make(fn, ln); - ret.type_tag = unsignednum_ast; - ret.value = value; - return ret; -} - -// Return an AST for a token -ast_token_t ast_token(const char *fn, unsigned int ln, int token_code) -{ - ast_token_t ret; - ret.file_loc = file_location_make(fn, ln); - ret.type_tag = token_ast; - ret.toknum = token_code; - return ret; -} - -// Requires: lst is a pointer to a non-circular linked list with next pointers -// in the same relative position as ast_generic_t -// Return a pointer to the last element in lst. -// This only returns NULL if lst == NULL. -void *ast_last_list_elem(void *lst) -{ - if (lst == NULL) { - return lst; - } - // assert lst is not NULL - void *prev = NULL; - while (lst != NULL) { - prev = lst; - lst = ((ast_generic_t *)lst)->next; - } - // here lst == NULL; - return prev; -} - -// Requires: lst is a pointer to a non-circular linked list with next pointers -// in the same relative position as ast_generic_t -// Return the number of elements in the linked list lst -extern int ast_list_length(void *lst) -{ - int ret = 0; - ast_generic_t *p = (ast_generic_t *) lst; - while (p != NULL) { - p = p->next; - ret++; - } - return ret; -} diff --git a/vm/ast.h b/vm/ast.h deleted file mode 100755 index 8826ea1..0000000 --- a/vm/ast.h +++ /dev/null @@ -1,422 +0,0 @@ -/* $Id: ast.h,v 1.35 2024/09/25 15:45:15 leavens Exp $ */ -#ifndef _AST_H -#define _AST_H -#include -#include "machine_types.h" -#include "file_location.h" -#include "instruction.h" - -// types of ASTs (type tags) -typedef enum { - program_ast, text_section_ast, addr_ast, asm_instr_ast, - asm_instrs_ast, label_opt_ast, empty_ast, instr_ast, - data_section_ast, data_size_ast, - static_decls_ast, static_decl_ast, initializer_opt_ast, - stack_section_ast, ident_ast, number_ast, unsignednum_ast, - reg_ast, token_ast, char_literal_ast, string_literal_ast -} AST_type; - -// forward declaration, so can use the type AST* below -typedef union AST_u AST; - -// The following types for structs named N_t -// are used in the declaration of the AST_u union below. -// The struct N_t is the type of information kept in the AST -// that is related to the nonterminal N in the abstract syntax. - -// The generic struct type (ast_generic_t) has the fields that -// should be in all alternatives of the AST union type (AST_u) -// (although the next field is only needed for those that can be in lists). -typedef struct { - file_location *file_loc; - AST_type type_tag; // says what field of the union is active - void *next; // for lists -} ast_generic_t; - -// empty ::= -typedef struct { - file_location *file_loc; - AST_type type_tag; -} ast_empty_t; - -// label ::= ident -typedef struct { - file_location *file_loc; - AST_type type_tag; - const char *name; -} ast_ident_t; - -// (signed) numbers (and offsets) -typedef struct { - file_location *file_loc; - AST_type type_tag; - word_type value; -} ast_number_t; - -// unsigned numbers -typedef struct { - file_location *file_loc; - AST_type type_tag; - const char *text; - uword_type value; -} ast_unsignednum_t; - -// registers -typedef struct { - file_location *file_loc; - AST_type type_tag; - const char *text; - unsigned short number; -} ast_reg_t; - -typedef enum { ds_word, ds_char, ds_string } data_size_e; - -// dataSize ::= WORD | CHAR | STRING [ ] -typedef struct { - file_location *file_loc; - AST_type type_tag; - data_size_e dse; - const char *size_name; - unsigned short size_in_words; -} ast_data_size_t; - -// tokens as ASTs -typedef struct { - file_location *file_loc; - AST_type type_tag; - const char *text; - int toknum; -} ast_token_t; - -// char literals as ASTs -typedef struct { - file_location *file_loc; - AST_type type_tag; - char value; -} ast_charliteral_t; - -// string literals as ASTs -typedef struct { - file_location *file_loc; - AST_type type_tag; - const char *pointer; -} ast_stringliteral_t; - - -// label-opt ::= label | empty -typedef struct { - file_location *file_loc; - AST_type type_tag; - const char *name; // NULL if there was no label -} ast_label_opt_t; - -// addr ::= label | unsigned-number -typedef struct { - file_location *file_loc; - AST_type type_tag; - bool address_defined; // has this address gotten a value? - const char *label; // NULL if address_defined (is true) - address_type addr; // 0 if !address_defined -} ast_addr_t; - -// kinds of immediate data -typedef enum { id_number, id_unsigned, id_addr, id_syscall_code, id_empty -} immed_data_kind_t; - -// immed-data ::= number | unsignednum | syscall-code | addr | empty -typedef struct { - immed_data_kind_t id_data_kind; - union { - immediate_type immed; // immediate arguments (not offsets!) - shift_type uimmed; // shifts - syscall_type syscall_code; - ast_addr_t addr; - } data; -} ast_immedData_t; - -// instr ::= no-arg-instr | two-reg-comp-instr | no-target-offset-instr -// | no-source-offset-instr | one-reg-arg-instr | one-reg-offset-instr -// | shift-instr | arg-only-instr | immed-arith-instr -// | immed-bool-astr | branch-test-instr | jump-instr | syscall-instr -typedef struct ast_instr_s { - file_location *file_loc; - AST_type type_tag; - struct ast_instr_s * next; - instr_type itype; - const char *opname; - op_code opcode; - func_type func; // function code for computational instructions - unsigned short regs_used; - reg_num_type reg; - offset_type offset; - reg_num_type reg2; // if there are two of registers - offset_type offset2; - ast_immedData_t immed_data; // includes arg (the number alternative) -} ast_instr_t; - -// asmInstr ::= label-opt instr -typedef struct asm_instr_s { - file_location *file_loc; - AST_type type_tag; - struct asm_instr_s *next; // for lists - ast_label_opt_t label_opt; - ast_instr_t instr; -} ast_asm_instr_t; - -// asmInstrs ::= asmInstr | asmInstrs asmInstr -typedef struct { - file_location *file_loc; - AST_type type_tag; - ast_asm_instr_t *instrs; -} ast_asm_instrs_t; - -// initializer kinds -typedef enum {initzlr_k_number, initzlr_k_char, initzlr_k_string, - initzlr_k_none - } initzlr_k; - -// initializer-opt ::= initializer | empty -typedef struct { - file_location *file_loc; - AST_type type_tag; - initzlr_k kind; - word_type num_value; // for numbers and char-literals - word_type byte_size; // for strings - const char *str_value; // for strings -} ast_initializer_opt_t; - -// staticDecl ::= dataSize ident initializer-opt -typedef struct static_decl_s { - file_location *file_loc; - AST_type type_tag; - struct static_decl_s *next; // for lists - unsigned short size_in_words; - data_size_e dse; - const char *size_name; - ast_ident_t ident; - ast_initializer_opt_t initializer; -} ast_static_decl_t; - -// staticDecls ::= staticDecl* -typedef struct { - file_location *file_loc; - AST_type type_tag; - ast_static_decl_t *decls; -} ast_static_decls_t; - -// text-section ::= entry-point asmInstr* -typedef struct { - file_location *file_loc; - AST_type type_tag; - ast_addr_t entryPoint; - ast_asm_instrs_t instrs; -} ast_text_section_t; - -// data-section ::= static-decl* -typedef struct { - file_location *file_loc; - AST_type type_tag; - address_type static_start_addr; - ast_static_decls_t staticDecls; -} ast_data_section_t; - -// stack-section ::= .stack stack-bottom-addr -typedef struct { - file_location *file_loc; - AST_type type_tag; - address_type stack_bottom_addr; -} ast_stack_section_t; - -// program ::= text-section data-section -typedef struct { - file_location *file_loc; - AST_type type_tag; - ast_text_section_t textSection; - ast_data_section_t dataSection; - ast_stack_section_t stackSection; -} ast_program_t; - -// The actual AST definition: -typedef union AST_u { - ast_generic_t generic; - ast_program_t program; - ast_text_section_t text_section; - ast_addr_t addr; - ast_asm_instrs_t asm_instrs; - ast_asm_instr_t asm_instr; - ast_label_opt_t label_opt; - ast_empty_t empty; - ast_instr_t instr; - ast_data_section_t data_section; - ast_static_decls_t static_decls; - ast_static_decl_t static_decl; - ast_data_size_t data_size; - ast_initializer_opt_t initializer; - ast_stack_section_t stack_section; - ast_ident_t ident; - ast_number_t number; - ast_unsignednum_t unsignednum; - ast_immedData_t immed; - ast_reg_t reg; - ast_token_t token; - ast_charliteral_t charlit; - ast_stringliteral_t stringlit; -} AST; - -// Return (a pointer to) the file location from an AST -extern const file_location *ast_file_loc(AST t); - -// Return the filename from the AST t -extern const char *ast_filename(AST t); - -// Return the line number from the AST t -extern unsigned int ast_line(AST t); - -// Return the type tag of the AST t -extern AST_type ast_type_tag(AST t); - -// Return an AST for a program, -// which contains the given ASTs. -extern ast_program_t ast_program(ast_text_section_t textSec, - ast_data_section_t dataSec, - ast_stack_section_t stackSec); - -// Return an AST for the text section -// with the given entry point and instructions. -extern ast_text_section_t ast_text_section(ast_token_t tok, ast_addr_t entryPoint, - ast_asm_instrs_t instrs); - -// Return an AST for an entry point -// that represents the label given -extern ast_addr_t ast_addr_label(ast_ident_t label); - -// Return an AST for an entry point -// that represents the address given -extern ast_addr_t ast_entry_addr(ast_unsignednum_t addr); - -// Return an AST for an asm instr AST -// with the given label and instruction -extern ast_asm_instr_t ast_asm_instr(ast_label_opt_t label, ast_instr_t instr); - -// Return an AST for a singleton asm instrs AST -// with the given instruction -extern ast_asm_instrs_t ast_asm_instrs_singleton(ast_asm_instr_t asminstr); - -// Return an AST made from adding the given asm instr to the end of lst -extern ast_asm_instrs_t ast_asm_instrs_add(ast_asm_instrs_t lst, ast_asm_instr_t asminstr); - -// Requires: id.name != NULL. -// Return an AST for a label_opt AST -// with the given identifier -extern ast_label_opt_t ast_label_opt_label(ast_ident_t id); - -// Return an AST for a label_opt AST -// with the empty AST (t) -extern ast_label_opt_t ast_label_opt_empty(ast_empty_t t); - -// Return an immediate data holding a number -extern ast_immedData_t ast_immed_number(word_type n); - -// Return an immediate data holding an unsigned int -extern ast_immedData_t ast_immed_unsigned(unsigned int u); - -// Requires: toknum is the token number of a system call operation. -// Return an immedidate data holding a system call code for t -extern ast_immedData_t ast_syscall_code_for(int toknum); - -// Return an immediate data holding an address -extern ast_immedData_t ast_immed_addr(ast_addr_t a); - -// Return an immediate data that is nothing -extern ast_immedData_t ast_immed_none(); - -// Return an instruction AST for a (no-argument) instruction -extern ast_instr_t ast_0arg_instr(ast_token_t op); - -// Return an instruction AST -// for a (2-register) computational instruction -extern ast_instr_t ast_2reg_instr(ast_token_t op, - unsigned short rt, offset_type ot, - unsigned short rs, offset_type os, - func_type func); - -// Return an AST for an instruction -// with the given information -extern ast_instr_t ast_1reg_instr(ast_token_t op, instr_type itype, - unsigned short num_regs_used, - unsigned short reg, offset_type offset, - func_type func, ast_immedData_t im); - -// Return an AST for the data section AST -// with the given list of static declarations. -extern ast_data_section_t ast_data_section(ast_token_t kw, unsigned int static_start, ast_static_decls_t staticDecls); - -// Return an AST for an empty list of static declarations -extern ast_static_decls_t ast_static_decls_empty(ast_empty_t e); - -// Return an AST for a list of static declarations -// with sd added to the end of sds -extern ast_static_decls_t ast_static_decls_add(ast_static_decls_t sds, - ast_static_decl_t sd); - -// Return an AST for a data size delclarator -// for the given number of words -extern ast_data_size_t ast_data_size(ast_token_t kw, data_size_e dse, - unsigned short words); - -// Requires: init.byte_size <= (ds.size_in_words * BYTES_PER_WORD). -// Return an AST for a static declaration -// with the given data size, identifier, and initializer. -// Note that the size is taken from the ds argument, not the initializer. -extern ast_static_decl_t ast_static_decl(ast_data_size_t ds, - ast_ident_t ident, - ast_initializer_opt_t init); - -// Return an AST for an initializer with the given number -extern ast_initializer_opt_t ast_initializer_number(ast_token_t eqs, - word_type value); - -// Return an AST for an initializer with the given char literal -extern ast_initializer_opt_t ast_initializer_char(ast_token_t eqs, - char c); - -// Return an AST for an initializer with the given string literal -extern ast_initializer_opt_t ast_initializer_string(ast_token_t eqs, - const char *s); - -// Return an AST for an empty initializer -extern ast_initializer_opt_t ast_initializer_empty(ast_empty_t e); - -// Return an AST for empty found in the file named fn, on line ln -extern ast_empty_t ast_empty(const char *fn, unsigned int ln); - -// Return an AST for a stack section AST -// with the given keyword and stack bottom address. -extern ast_stack_section_t ast_stack_section(ast_token_t kw, - unsigned int stack_bottom); - -// found in the file named fn, on line ln, with the given name. -extern ast_ident_t ast_ident(const char *fn, unsigned int ln, const char *name); - -// Return an AST for a (signed) number with the given value -extern ast_number_t ast_number(ast_token_t sgn, word_type value); - -// Return an AST for a (signed) number with the given value -extern ast_unsignednum_t ast_unsigned_number(const char *fn, unsigned int ln, - unsigned int value); - -// Return an AST for a token -extern ast_token_t ast_token(const char *fn, unsigned int ln, int token_code); - -// Requires: lst is a pointer to a non-circular linked list with next pointers -// in the same relative position as ast_generic_t -// Return a pointer to the last element in lst. -// This only returns NULL if lst == NULL. -extern void *ast_last_list_elem(void *lst); - -// Requires: lst is a pointer to a non-circular linked list with next pointers -// in the same relative position as ast_generic_t -// Return the number of elements in the linked list lst -extern int ast_list_length(void *lst); - -#endif diff --git a/vm/bof.c b/vm/bof.c deleted file mode 100755 index 8597cff..0000000 --- a/vm/bof.c +++ /dev/null @@ -1,193 +0,0 @@ -/* $Id: bof.c,v 1.19 2024/07/28 22:01:51 leavens Exp $ */ -// #include -#include -// #include -#include -#include -#include -#include "bof.h" -#include "utilities.h" - -#define MAGIC "BO32" - -// a type for treating bytes as a word -typedef union { - unsigned char buf[BYTES_PER_WORD]; - word_type w; -} word_pun_t; - -// Open filename for reading as a binary file -// Exit the program with an error if this fails, -// otherwise return the BOFFILE struct for the file -BOFFILE bof_read_open(const char *filename) { - BOFFILE bf; - bf.fileptr = fopen(filename, "rb"); - bf.filename = filename; - - if (bf.fileptr == NULL) { - bail_with_error("Error opening file for reading: %s", filename); - } - - return bf; -} - -// Return the size (in bytes) of bf -size_t bof_file_bytes(BOFFILE bf) -{ - struct stat st; - if (stat(bf.filename, &st) < 0) { - bail_with_error("Cannot stat %s to get its size!", bf.filename); - } - ; - return st.st_size; -} - -// Return true just when bf is at its end, false otherwise -bool bof_at_eof(BOFFILE bf) { - return feof(bf.fileptr); -} - -// Requires: bf is open for reading in binary and has -// at least BYTES_PER_WORD bytes in it -// Return the next word from bf -word_type bof_read_word(BOFFILE bf) -{ - word_pun_t b; - assert(!bof_at_eof(bf)); - size_t bytes_read = bof_read_bytes(bf, BYTES_PER_WORD, b.buf); - if (bytes_read == 0) { - bail_with_error( - "Cannot read a word from %s (got %d bytes), at EOF: %d", - bf.filename, bytes_read, bof_at_eof(bf)); - } - return b.w; -} - -// Requires: bf.fileptr is open for reading in binary -// and buf is of size at least bytes -// Read the given number of bytes into buf and return the number of bytes read -size_t bof_read_bytes(BOFFILE bf, size_t bytes, void *buf) { - int elems_read = fread(buf, bytes, 1, bf.fileptr); - return elems_read; -} - -// Requires: bf is open for reading in binary -// Read the header of bf as a BOFHeader and return that header -// If any errors are encountered, exit with an error message. -BOFHeader bof_read_header(BOFFILE bf) { - BOFHeader ret; - size_t rd = fread(&ret, sizeof(ret), 1, bf.fileptr); - if (rd != 1) { - bail_with_error("Cannot read header from %s", bf.filename); - } - if (!bof_has_correct_magic_number(ret)) { - bail_with_error("Wrong magic number code in file '%s'!", - bf.filename); - } - return ret; - /* - bof_read_bytes(bf, MAGIC_BUFFER_SIZE, &ret.magic); - if (strncmp(ret.magic, MAGIC, MAGIC_BUFFER_SIZE) != 0) { - bail_with_error("File %s is not a BOF format file, bad magic number!", - bf.filename); - } - bof_read_bytes(bf, BYTES_PER_WORD, &ret.text_start_address); - bof_read_bytes(bf, BYTES_PER_WORD, &ret.text_length); - bof_read_bytes(bf, BYTES_PER_WORD, &ret.data_start_address); - bof_read_bytes(bf, BYTES_PER_WORD, &ret.data_length); - bof_read_bytes(bf, BYTES_PER_WORD, &ret.stack_bottom_addr); - return ret; - */ -} - -// Requires: f is open for writing -// Write the magic number in hexadecimal notation on f, followed by a newline; -// Note: this is just for help in writing the documentation -/* -void bof_write_magic(FILE *f) { - fprintf(f, "%s", "0x"); - for (int i = 0; i < MAGIC_BUFFER_SIZE; i++) { - fprintf(f, "%x", MAGIC[i]); - } - fprintf(f, "\n"); -} -*/ - -// Open filename for writing as a binary file -// Exit the program with an error if this fails, -// otherwise return the BOFFILE for it. -BOFFILE bof_write_open(const char *filename) { - BOFFILE bf; - bf.fileptr = fopen(filename, "wb"); - bf.filename = filename; - - if (bf.fileptr == NULL) { - bail_with_error("Error opening file for writing: %s", filename); - } - - return bf; -} - -// Requres: bf is open -// Close the given binary file -// Exit the program with an error if this fails. -void bof_close(BOFFILE bf) -{ - if (fclose(bf.fileptr) != 0) { - bail_with_error("Could not close %s", bf.filename); - } -} - - -// Requires: bf is open for writing in binary. -// Write the given word into bf -// Exit the program with an error if this fails. -extern void bof_write_word(BOFFILE bf, word_type w) -{ - word_pun_t b; - b.w = w; - bof_write_bytes(bf, BYTES_PER_WORD, b.buf); -} - -// Requires: bf is open for writing in binary -// and the size of buf is at least bytes -// Write the given number of bytes from buf into f. -// Exit the program with an error if this fails. -void bof_write_bytes(BOFFILE bf, size_t bytes, - const void *buf) { - size_t wr = fwrite(buf, bytes, 1, bf.fileptr); - if (wr != 1) { - bail_with_error("Cannot write %u bytes to %s", bytes, bf.filename); - } -} - -// Requires: bf is open for writing in binary -// Write the given header to f -// Exit the program with an error if this fails. -void bof_write_header(BOFFILE bf, const BOFHeader hdr) { - size_t wr = fwrite(&hdr, sizeof(BOFHeader), 1, bf.fileptr); - if (wr != 1) { - bail_with_error("Canot write header to %s", bf.filename); - } -} - -// Write the (bits of the) magic number into the header bh. -void bof_write_magic_to_header(BOFHeader *bh) -{ - const char *magic = MAGIC; - for (int i = 0; i < MAGIC_BUFFER_SIZE; i++) { - bh->magic[i] = magic[i]; - } - assert(bof_has_correct_magic_number(*bh)); -} - -// Does the given header have the appropriate magic number? -bool bof_has_correct_magic_number(BOFHeader bh) -{ - char buf[MAGIC_BUFFER_SIZE+1]; - for (int i = 0; i < MAGIC_BUFFER_SIZE; i++) { - buf[i] = bh.magic[i]; - } - buf[MAGIC_BUFFER_SIZE] = '\0'; - return (0 == strncmp(buf, MAGIC, MAGIC_BUFFER_SIZE)); -} diff --git a/vm/bof.h b/vm/bof.h deleted file mode 100755 index 70d603c..0000000 --- a/vm/bof.h +++ /dev/null @@ -1,88 +0,0 @@ -/* $Id: bof.h,v 1.22 2024/08/20 00:46:41 leavens Exp $ */ -// Binary Object File Format (for the SSM) -#ifndef _BOF_H -#define _BOF_H -#include -#include -#include -#include "machine_types.h" - -#define MAGIC_BUFFER_SIZE 4 - -typedef struct { // Field magic should hold value of MAGIC (with no null char) - char magic[MAGIC_BUFFER_SIZE]; - word_type text_start_address; // word address to start running (PC) - word_type text_length; // size of the text section in words - word_type data_start_address; // word address of static data (GP) - word_type data_length; // size of data section in words - word_type stack_bottom_addr; // word address of stack "bottom" (FP) -} BOFHeader; - -// a type for Binary Output Files -typedef struct { - FILE *fileptr; - const char *filename; -} BOFFILE; - -// Open filename for reading as a binary file -// Exit the program with an error if this fails, -// otherwise return the FILE pointer to the open file. -extern BOFFILE bof_read_open(const char *filename); - -// Return the size (in bytes) of bf -extern size_t bof_file_bytes(BOFFILE bf); - -// Return true just when bf is at its end, false otherwise -extern bool bof_at_eof(BOFFILE bf); - -// Requires: bf is open for reading in binary and has -// at least 1 word (2 bytes) available to read -// Return the next word from bf -extern word_type bof_read_word(BOFFILE bf); - -// Requires: bf is open for reading in binary and -// buf is of size at least bytes -// Read the given number of bytes into buf and return the number of bytes read -size_t bof_read_bytes(BOFFILE bf, size_t bytes, void *buf); - -// Requires: bf is open for reading in binary -// Read the header of bf as a BOFHeader and return that header -// If any errors are encountered, exit with an error message. -extern BOFHeader bof_read_header(BOFFILE); - -// Open filename for writing as a binary file -// Exit the program with an error if this fails, -// otherwise return the BOFFILE for it. -extern BOFFILE bof_write_open(const char *filename); - -// Requres: bf is open -// Close the given binary file -// Exit the program with an error if this fails. -extern void bof_close(BOFFILE bf); - -// Requires: bf is open for writing in binary -// Write the given word into bf. -// Exit the program with an error if this fails. -extern void bof_write_word(BOFFILE bf, word_type w); - -// Requires: bf is open for writing in binary -// and the size of buf is at least bytes -// Write the given number of bytes from buf into f. -// Exit the program with an error if this fails. -extern void bof_write_bytes(BOFFILE bf, size_t bytes, - const void *buf); - -// Requires: bf is open for writing in binary -// Write the given header to f -// Exit the program with an error if this fails. -extern void bof_write_header(BOFFILE bf, const BOFHeader hdr); - -// Write the (bits of the) magic number into the header *bh. -extern void bof_write_magic_to_header(BOFHeader *bh); - -// Does the given header have the appropriate magic number? -bool bof_has_correct_magic_number(BOFHeader bh); - -// The following line is for the manual (i.e., the document itself)y -// ... -#endif diff --git a/vm/bof_bin_dump.c b/vm/bof_bin_dump.c deleted file mode 100755 index 1da4be4..0000000 --- a/vm/bof_bin_dump.c +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include -#include "bof.h" -#include "machine_types.h" -#include "utilities.h" - -#define BITS_PER_BYTE 8 -#define BUFF_SIZE (BITS_PER_BYTE*sizeof(word_type) + 1) - -/* Requires: buff has size at least (BITS_PER_BYTE*sizeof(word_type)+1). - Put binary digit characters corresponding to val into buff - Modified from https://stackoverflow.com/questions/699968/display-the-binary-representation-of-a-number-in-c -*/ -static const char *binrep (unsigned int val, char *buff) { - char *pbuff = buff; - int bit_sz = BITS_PER_BYTE * sizeof(word_type); // bit size - - /* Work from the end of the buffer back. */ - pbuff += bit_sz; - *pbuff-- = '\0'; - - /* For each bit (going backwards) store character. */ - while (1) { - if (bit_sz-- < 0) { // when previous bit size was 0, so did 0th bit - return buff; - } - *pbuff-- = ((val & 1) ? '1' : '0'); - /* Get next bit. */ - val >>= 1; - } -} - - -// Print a usage message on stderr and exit with exit code 1. -static void usage(const char *cmdname) -{ - bail_with_error("Usage: %s file.bof", cmdname); -} - - -int main(int argc, char *argv[]) { - if (argc >= 2) { - BOFFILE bf = bof_read_open(argv[1]); - size_t siz = bof_file_bytes(bf); // size in bytes - char *suffix = strchr(argv[1], '.'); - if (suffix == NULL || strncmp(suffix, ".bof", 4) != 0) { - usage(argv[0]); - } - - char bits_buff[BUFF_SIZE]; - printf("Addr\t= Binary\t\t\t\t= Unsigned\t= Signed\t= Hexadecimal\n"); - for (address_type a = 0; - a*BYTES_PER_WORD < siz && !bof_at_eof(bf); a++) { - if (a == sizeof(BOFHeader) / BYTES_PER_WORD) { - printf("---- end of header ----\n"); - } - word_type w = bof_read_word(bf); - printf("%hu:", a / BYTES_PER_WORD); - printf("\t= %s", binrep((unsigned int) w, - bits_buff)); - printf("\t= %10u", w); - printf("\t= %10d", w); - printf("\t= 0x%x\n", w); - } - } else { - bail_with_error("Cannot read %s!", argv[1]); - } - return EXIT_SUCCESS; -} diff --git a/vm/char_utilities.c b/vm/char_utilities.c deleted file mode 100755 index b0b17db..0000000 --- a/vm/char_utilities.c +++ /dev/null @@ -1,158 +0,0 @@ -// $Id: char_utilities.c,v 1.4 2024/07/26 02:31:21 leavens Exp $ -#include -#include -#include "char_utilities.h" -#include "utilities.h" - -// strdup seems to be in the string library but not in the header... -extern char *strdup(const char *s); - -// return the value of the given character literal -// and set *charlit_len to the number of characters in the literal read -unsigned char char_utilities_char_value(const char *lit, - int *charlit_len) -{ - int len = strlen(lit); - assert(len > 0); - if (len < 2 || lit[0] != '\\') { - *charlit_len = 1; - return lit[0]; - } - // now we know that lit[0] is a backslash - *charlit_len = 2; // adjusted below for octal and hex literals - // lit is an escape sequence, with lit[0] == '\\' - switch (lit[1]) { - case 'n': - return '\n'; - break; - case 'r': - return '\r'; - break; - case 'f': - return '\f'; - break; - case 't': - return '\t'; - break; - case 'v': - return '\v'; - break; - case '0': - if (len == 2 || (len > 2 && !is_octal_digit(lit[3]))) { - return '\0'; - } else { - // octal escape sequence - unsigned int val; - sscanf(lit+2, "%o", &val); - int digits_after_0 = 0; - while (is_octal_digit(lit[2+digits_after_0])) { - digits_after_0++; - } - *charlit_len = 2 + digits_after_0; - return (unsigned char)val; - } - break; - case 'a': - return '\a'; - break; - case 'b': - return '\b'; - break; - case '\\': - return '\\'; - break; - case '\'': - return '\''; - break; - case '\"': - return '\"'; - break; - case 'x': - // hex escape sequence - unsigned int val; - sscanf(lit+2, "%x", &val); - int digits_after_x = 0; - while (isxdigit((int)lit[2+digits_after_x])) { - digits_after_x++; - } - *charlit_len = 2 + digits_after_x; - return (unsigned char)val; - break; - default: - return (unsigned char)lit[1]; - break; - } -} - -// Return the given char as a string -// or, if it's not printable, then return a literal string for it -const char *char_utilities_unescape_char(unsigned char c) -{ - char unescape_buf[20]; // allow for longer octal escapes (for errors) - if (isprint(c) && c != '\\' && c != '\n' && c != '\'' && c != '\"') { - sprintf(unescape_buf, "%c", c); - } else { - switch (c) { - case '\n': - sprintf(unescape_buf, "\\n"); - break; - case '\r': - sprintf(unescape_buf, "\\r"); - break; - case '\f': - sprintf(unescape_buf, "\\f"); - break; - case '\t': - sprintf(unescape_buf, "\\t"); - break; - case '\v': - sprintf(unescape_buf, "\\v"); - break; - case '\0': - sprintf(unescape_buf, "\\0"); - break; - case '\a': - sprintf(unescape_buf, "\\a"); - break; - case '\b': - sprintf(unescape_buf, "\\b"); - break; - case '\\': - sprintf(unescape_buf, "\\\\"); - break; - case '\'': - sprintf(unescape_buf, "\\'"); - break; - case '\"': - sprintf(unescape_buf, "\\\""); - break; - default: - sprintf(unescape_buf, "\\0%o", c); - break; - } - } - return strdup(unescape_buf); -} - -#define UNESTRBUFSIZE 4096 - -// Return the given string as a string with only -// printable characters and escape sequences -const char *char_utilities_unescape_string(const char *s) -{ - char buf[UNESTRBUFSIZE]; - int len = strlen(s); - int buff_index = 0; - for (int i = 0; i < len; i++) { - buff_index - += sprintf(buf+buff_index, "%s", - char_utilities_unescape_char((unsigned char) s[i])); - } - return strdup(buf); -} - -// Is the given character an octal digit (0-7)? -bool is_octal_digit(char c) -{ - return ('0' <= c && c <= '7'); -} diff --git a/vm/char_utilities.h b/vm/char_utilities.h deleted file mode 100755 index b7bfb8d..0000000 --- a/vm/char_utilities.h +++ /dev/null @@ -1,23 +0,0 @@ -// $Id: char_utilities.h,v 1.3 2024/07/26 02:31:21 leavens Exp $ -#ifndef CHAR_UTILTIES_H -#define CHAR_UTILTIES_H - -#include - -// return the value of the given character literal -// and set *charlit_len to the number of characters in the literal read -extern unsigned char char_utilities_char_value(const char *lit, - int *charlit_len); - -// Return a the given char as a string -// or, if it's not printable, then return a literal string for it -extern const char *char_utilities_unescape_char(unsigned char c); - -// Return the given string as a string with only -// printable characters and escape sequences -extern const char *char_utilities_unescape_string(const char *s); - -// Is the given character an octal digit (0-7)? -extern bool is_octal_digit(char c); - -#endif diff --git a/vm/check-tests.sh b/vm/check-tests.sh deleted file mode 100755 index b2a0a83..0000000 --- a/vm/check-tests.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -: ${PREFIX=lexer_test} -for i in $@ -do - emacs ${PREFIX}${i}.lst ${PREFIX}${i}.asm && emacs ${PREFIX}${i}.asm ${PREFIX}${i}.out -done diff --git a/vm/disasm.c b/vm/disasm.c deleted file mode 100755 index 3857ab7..0000000 --- a/vm/disasm.c +++ /dev/null @@ -1,91 +0,0 @@ -/* $Id: disasm.c,v 1.14 2024/07/28 22:01:51 leavens Exp $ */ -#include -#include "disasm.h" -#include "bof.h" -#include "regname.h" -#include "utilities.h" -#include "instruction.h" - -// Disassemble code from bf, -// with output going to the file out -void disasmProgram(FILE *out, BOFFILE bf) -{ - BOFHeader bh = bof_read_header(bf); - disasmTextSection(out, bf, bh); - disasmDataSection(out, bf, bh); - disasmStackSection(out, bh); - fprintf(out, ".end"); - newline(out); -} - -// Disassemble the text section -// with output going to the file out -void disasmTextSection(FILE *out, BOFFILE bf, BOFHeader bh) -{ - fprintf(out, ".text\t%u", bh.text_start_address); - newline(out); - disasmInstrs(out, bf, bh.text_length); -} - -// Disassemble length instructions from bf -// with output going to the file out -void disasmInstrs(FILE *out, BOFFILE bf, int length) -{ - for (int i = 0; i < length; i++) { - disasmInstr(out, instruction_read(bf), i); - } -} - -// Disassemble the binary instruction bi, which would go at address i -// each instruction has a label of the form a%d:, where %d is the value of i -void disasmInstr(FILE *out, bin_instr_t bi, address_type i) -{ - fprintf(out, "a%d:\t%s", i, instruction_assembly_form(i, bi)); - newline(out); -} - -// Disassemble the data section from bf, based on the information in bh, -// with output going to out -void disasmDataSection(FILE *out, BOFFILE bf, BOFHeader bh) -{ - fprintf(out, ".data\t%u", bh.data_start_address); - newline(out); - disasmStaticDecls(out, bf, bh.data_length); -} - -// Disassemble words_to_read static data words from bf, -// with output going to out -void disasmStaticDecls(FILE *out, BOFFILE bf, int words_to_read) -{ - while (words_to_read >= 1) { - disasmStaticDecl(out, bof_read_word(bf)); - words_to_read--; - } -} - -// count of number of words generated, to get unique names -static int word_count = 0; -// buffer for generated ids -static char id_buf[16]; - -static const char*new_word_id() -{ - sprintf(id_buf, "w%x", word_count); - word_count++; - return id_buf; -} - -// Disassemble the the given word as a static data declaration, -// with output going to out -void disasmStaticDecl(FILE *out, word_type w) -{ - fprintf(out, "WORD %s = %d", new_word_id(), w); - newline(out); -} - -// Disassemble the stack section based on the given header information -void disasmStackSection(FILE *out, BOFHeader bh) -{ - fprintf(out, ".stack\t%u", bh.stack_bottom_addr); - newline(out); -} diff --git a/vm/disasm.h b/vm/disasm.h deleted file mode 100755 index b542d22..0000000 --- a/vm/disasm.h +++ /dev/null @@ -1,37 +0,0 @@ -// $Id: disasm.h,v 1.6 2024/07/25 20:33:43 leavens Exp $ -#ifndef _DISASM_H -#define _DISASM_H -#include "instruction.h" - -// Disassemble code from bf, -// with output going to the file out -extern void disasmProgram(FILE *out, BOFFILE bf); - -// Disassemble the text section -// with output going to the file out -extern void disasmTextSection(FILE *out, BOFFILE bf, BOFHeader bh); - -// Disassemble length instructions from bf -// with output going to the file out -extern void disasmInstrs(FILE *out, BOFFILE bf, int length); - -// Disassemble the binary instruction bi, which would go at address i -// each instruction has a label of the form a%d, where %d is the value of i -extern void disasmInstr(FILE *out, bin_instr_t bi, address_type i); - -// Disassemble the data section from bf, based on the information in bh, -// with output going to out -extern void disasmDataSection(FILE *out, BOFFILE bf, BOFHeader bh); - -// Disassemble words_to_read static data words from bf, -// with output going to out -extern void disasmStaticDecls(FILE *out, BOFFILE bf, int words_to_read); - -// Disassemble the the given word as a static data declaration, -// with output going to out -extern void disasmStaticDecl(FILE *out, word_type w); - -// Disassemble the stack section based on the given header information -extern void disasmStackSection(FILE *out, BOFHeader bh); - -#endif diff --git a/vm/disasm_main.c b/vm/disasm_main.c deleted file mode 100755 index beaa5a0..0000000 --- a/vm/disasm_main.c +++ /dev/null @@ -1,32 +0,0 @@ -/* $Id: disasm_main.c,v 1.3 2023/09/16 12:32:30 leavens Exp $ */ -#include -#include -#include "bof.h" -#include "disasm.h" -#include "utilities.h" - -static char *progname; - -void usage() { - bail_with_error("Usage: %s file.bof", progname); -} - -int main(int argc, char *argv[]) { - // set the program's name - progname = argv[0]; - argc--; - argv++; - - if (argc != 1) { - usage(); - } - - // name of the file to read - const char *bofname = argv[0]; - - BOFFILE bf = bof_read_open(bofname); - - disasmProgram(stdout, bf); - - return EXIT_SUCCESS; -} diff --git a/vm/error_vm_test1.asm b/vm/error_vm_test1.asm deleted file mode 100755 index 8fe88b4..0000000 --- a/vm/error_vm_test1.asm +++ /dev/null @@ -1,9 +0,0 @@ - # $Id: error_vm_test1.asm,v 1.1 2023/09/18 03:32:18 leavens Exp $ - .text start -start: ADDI $0, $t0, 1 - ADD $0, $t0, $fp - EXIT - .data 1024 - .stack 4096 - .end - diff --git a/vm/file_location.c b/vm/file_location.c deleted file mode 100755 index 9cc66e2..0000000 --- a/vm/file_location.c +++ /dev/null @@ -1,31 +0,0 @@ -/* $Id: file_location.c,v 1.3 2023/09/10 13:28:44 leavens Exp $ */ -#include -#include -#include "file_location.h" -#include "utilities.h" - -// Requires: filename != NULL -// Return a (pointer to a) fresh file_location with the given -// information -file_location *file_location_make(const char *filename, - unsigned int line) -{ - file_location *ret = (file_location *) malloc(sizeof(file_location)); - if (ret == NULL) { - bail_with_error("Could not allocate space for a file_location!"); - } - return ret; -} - -// Requires: fl != NULL -// Return a (pointer to a) fresh copy of fl -file_location *file_location_copy(file_location *fl) -{ - file_location *ret = (file_location *) malloc(sizeof(file_location)); - if (ret == NULL) { - bail_with_error("Could not allocate space for a file_location!"); - } - ret->filename = fl->filename; - ret->line = fl->line; - return ret; -} diff --git a/vm/file_location.h b/vm/file_location.h deleted file mode 100755 index 748867d..0000000 --- a/vm/file_location.h +++ /dev/null @@ -1,21 +0,0 @@ -/* $Id: file_location.h,v 1.2 2023/09/09 20:45:49 leavens Exp $ */ -#ifndef _FILE_LOCATION_H -#define _FILE_LOCATION_H - -// location in a source file (useful for error messages) -typedef struct { - const char *filename; - unsigned int line; // of first token -} file_location; - -// Requires: filename != NULL -// Return a (pointer to a) fresh file_location with the given -// information -extern file_location *file_location_make(const char *filename, - unsigned int line); - -// Requires: fl != NULL -// Return a (pointer to a) fresh copy of fl -extern file_location *file_location_copy(file_location *fl); - -#endif diff --git a/vm/hexdump.sh b/vm/hexdump.sh deleted file mode 100755 index e2b1e34..0000000 --- a/vm/hexdump.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -# dump the given file in hex, with a big-endian format -od --endian=big -t x4 "$@" diff --git a/vm/id_attrs.h b/vm/id_attrs.h deleted file mode 100755 index 7995510..0000000 --- a/vm/id_attrs.h +++ /dev/null @@ -1,19 +0,0 @@ -/* $Id: id_attrs.h,v 1.1 2023/09/11 04:19:57 leavens Exp $ */ -#ifndef _ID_ATTRS_H -#define _ID_ATTRS_H - -#include "machine_types.h" -#include "file_location.h" - -// Kinds of names in the assembly language -typedef enum {id_label, id_data} id_attr_kind; - -// attributes of a name in the assembly language -typedef struct { - const char *name; - id_attr_kind kind; - file_location *file_loc; - address_type addr; // offset from start of text or data section -} id_attrs; - -#endif diff --git a/vm/id_attrs_assoc.h b/vm/id_attrs_assoc.h deleted file mode 100755 index e422a43..0000000 --- a/vm/id_attrs_assoc.h +++ /dev/null @@ -1,19 +0,0 @@ -/* $Id: id_attrs_assoc.h,v 1.3 2024/07/29 02:01:32 leavens Exp $ */ -#ifndef _ID_ATTRS_ASSOC_H -#define _ID_ATTRS_ASSOC_H - -#include "machine_types.h" -#include "file_location.h" - -// Kinds of names in the assembly language -typedef enum {id_label, id_data} id_attr_kind; - -// attributes of a name in the assembly language -typedef struct { - const char *name; - id_attr_kind kind; - file_location *file_loc; - address_type addr; // word offset from start of text or data section -} id_attrs_assoc; - -#endif diff --git a/vm/instruction.c b/vm/instruction.c deleted file mode 100755 index 27513c9..0000000 --- a/vm/instruction.c +++ /dev/null @@ -1,610 +0,0 @@ -// $Id: instruction.c,v 1.61 2024/11/10 14:34:25 leavens Exp $ -#include -#include -#include "bof.h" -#include "instruction.h" -#include "regname.h" -#include "utilities.h" -#include "machine_types.h" -#include "asm.tab.h" - -#define INSTR_BUF_SIZE 512 - -// the following declaration isn't in everywhere ... -extern char *strdup(const char *s); - -// space to hold one instruction's assembly language form -static char instr_buf[INSTR_BUF_SIZE]; - -// Return the instruction type of the given opcode -instr_type instruction_type(bin_instr_t i) { - switch (i.comp.op) { // need to pretend a type to read the op field - case COMP_O: - return comp_instr_type; - break; - case OTHC_O: - if (i.othc.func == SYS_F) { - return syscall_instr_type; - } else { - assert(i.othc.op != COMP_O); - assert(i.othc.func != NOP_F); - return other_comp_instr_type; - } - break; - case ADDI_O: case ANDI_O: case BORI_O: case NORI_O: case XORI_O: - case BEQ_O: case BGEZ_O: case BGTZ_O: case BLEZ_O: case BLTZ_O: - case BNE_O: - return immed_instr_type; - break; - case JMPA_O: case CALL_O: case RTN_O: - return jump_instr_type; - break; - default: - return error_instr_type; - break; - } -} - -// Requires: bof is open for reading in binary -// Read a single instruction (in binary) from bf and return it, -// but exit with an error if there is a problem. -bin_instr_t instruction_read(BOFFILE bf) -{ - bin_instr_t bi; - size_t rd = fread(&bi, sizeof(bi), 1, bf.fileptr); - if (rd != 1) { - bail_with_error("Cannot read instruction from %s (read %d instrs)", - bf.filename, rd); - } - return bi; -} - -// Requires: bf is open for writing in binary -// Write the given binary instruction to bf, -// but exit with an error if there is a problem. -static void write_bin_instr(BOFFILE bf, bin_instr_t i) -{ - size_t wr = fwrite(&i, sizeof(i), 1, bf.fileptr); - if (wr != 1) { - bail_with_error("Cannot write binary instr to %s", bf.filename); - } -} - -// Requires: bof is open for writing in binary -// Write the binary instruction bi to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_bin_instr(BOFFILE bf, bin_instr_t bi) -{ - switch (instruction_type(bi)) { - case comp_instr_type: - instruction_write_compInstr(bf, bi.comp); - break; - case other_comp_instr_type: - instruction_write_otherCompInstr(bf, bi.othc); - break; - case immed_instr_type: - instruction_write_immedInstr(bf, bi.immed); - break; - case jump_instr_type: - instruction_write_jumpInstr(bf, bi.jump); - break; - case syscall_instr_type: - instruction_write_syscallInstr(bf, bi.syscall); - break; - default: - bail_with_error("Unknown instruction type in instruction_write_bin_instr (%d)", - instruction_type(bi)); - break; - } -} - - -// Requires: bof is open for writing in binary -// Write the computational instruction ci to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_compInstr(BOFFILE bf, comp_instr_t ci) -{ - bin_instr_t bi; - bi.comp = ci; - assert(bi.comp.op == ci.op); - assert(bi.comp.rt == ci.rt); - assert(bi.comp.ot == ci.ot); - assert(bi.comp.rs == ci.rs); - assert(bi.comp.os == ci.os); - assert(bi.comp.func == ci.func); - assert(bi.comp.func != NOP_F || bi.comp.op == COMP_O); - write_bin_instr(bf, bi); -} - -// Requires: bof is open for writing in binary -// Write the other computational instruction oci to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_otherCompInstr(BOFFILE bf, other_comp_instr_t oci) -{ - bin_instr_t bi; - bi.othc = oci; - - assert(bi.othc.op == oci.op); - assert(bi.othc.reg == oci.reg); - assert(bi.othc.offset == oci.offset); - assert(bi.othc.arg == oci.arg); - assert(bi.othc.func == oci.func); - - write_bin_instr(bf, bi); -} - -// Requires: bof is open for writing in binary -// Write the system instruction si to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_syscallInstr(BOFFILE bf, syscall_instr_t si) -{ - bin_instr_t bi; - bi.syscall = si; - /* - assert(bi.syscall.op == OTHC_O); - assert(bi.syscall.reg == si.reg); - assert(bi.syscall.offset == si.offset); - assert(bi.syscall.code == si.code); - assert(bi.syscall.func == SYS_F); - */ - write_bin_instr(bf, bi); -} - -// Requires: bof is open for writing in binary -// Write the immediate instruction ii to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_uimmedInstr(BOFFILE bf, uimmed_instr_t ui) -{ - bin_instr_t bi; - bi.uimmed = ui; - /* - assert(bi.uimmed.op == op); - assert(bi.uimmed.reg == ui.reg); - assert(bi.uimmed.offset == ui.offset); - assert(bi.uimmed.uimmed == ui.uimmed); - */ - write_bin_instr(bf, bi); -} - -// Requires: bof is open for writing in binary -// Write the immediate instruction ii to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_immedInstr(BOFFILE bf, immed_instr_t ii) -{ - bin_instr_t bi; - bi.immed = ii; - /* - assert(bi.immed.op == op); - assert(bi.immed.reg == ii.reg); - assert(bi.immed.offset == ii.offset); - assert(bi.immed.immed == ii.immed); - */ - write_bin_instr(bf, bi); -} - -// Requires: bof is open for writing in binary -// Write the jump instruction ji with opcode op to bf in binary, -// but exit with an error if there is a problem. -void instruction_write_jumpInstr(BOFFILE bf, jump_instr_t ji) -{ - bin_instr_t bi; - bi.jump = ji; - /* - assert(bi.jump.op == op); - assert(bi.jump.addr == ji.addr); - */ - write_bin_instr(bf, bi); -} - -// Return the assembly language name (mnemonic) for bi -const char *instruction_mnemonic(bin_instr_t bi) { - switch (bi.comp.op) { // pretending a type is needed to get the op field - case COMP_O: - return instruction_compFunc2name(bi); - break; - case OTHC_O: - return instruction_otherCompFunc2name(bi); - break; - case ADDI_O: - return "ADDI"; - break; - case ANDI_O: - return "ANDI"; - break; - case BORI_O: - return "BORI"; - break; - case NORI_O: - return "NORI"; - break; - case XORI_O: - return "XORI"; - break; - case BEQ_O: - return "BEQ"; - break; - case BGEZ_O: - return "BGEZ"; - break; - case BGTZ_O: - return "BGTZ"; - break; - case BLEZ_O: - return "BLEZ"; - break; - case BLTZ_O: - return "BLTZ"; - break; - case BNE_O: - return "BNE"; - break; - case JMPA_O: - return "JMPA"; - break; - case CALL_O: - return "CALL"; - break; - case RTN_O: - return "RTN"; - break; - default: - bail_with_error("Unknown op code (%d) in instruction_mnemonic!", - bi.immed.op); - return NULL; // should never happen - } - return NULL; // should never happen -} - -static char address_comment_buf[512]; - -// return a comment string of the form -// "# target is word address %u" -// that uses the formAddress function to get the proper address -static const char *instruction_formAddress_comment(address_type addr, - address_type a) -{ - address_type actual = machine_types_formAddress(addr, a); - sprintf(address_comment_buf, "# target is word address %u", - actual); - return strdup(address_comment_buf); -} - - -// Return a string containing the assembly language form of instr, -// which is found at address addr -const char *instruction_assembly_form(address_type addr, - bin_instr_t instr) -{ - char *buf = instr_buf; - - // put in the mnemonic for the instruction - int cwr = sprintf(buf, "%s ", instruction_mnemonic(instr)); - // point buf to the null char that was printed into instr_buf - buf += cwr; - - instr_type it = instruction_type(instr); - switch (it) { - case comp_instr_type: - switch (instr.comp.func) { - case NOP_F: - // no arguments for NOP! - break; - case ADD_F: case SUB_F: case CPW_F: - case AND_F: case BOR_F: case NOR_F: case XOR_F: - case SCA_F: case LWI_F: case NEG_F: - sprintf(buf, "%s, %hd, %s, %hd", - regname_get(instr.comp.rt), - instr.comp.ot, - regname_get(instr.comp.rs), - instr.comp.os); - break; - case CPR_F: - sprintf(buf, "%s, %s", - regname_get(instr.comp.rt), - regname_get(instr.comp.rs)); - break; - case LWR_F: - sprintf(buf, "%s, %s, %hd", - regname_get(instr.comp.rt), - regname_get(instr.comp.rs), - instr.comp.os); - break; - case SWR_F: - sprintf(buf, "%s, %hd, %s", - regname_get(instr.comp.rt), - instr.comp.ot, - regname_get(instr.comp.rs)); - break; - default: - bail_with_error("Unknown computational instruction function (%d) for mnemonic %s!", - instr.comp.func, buf); - break; - } - break; - case other_comp_instr_type: - assert(instr.othc.op == OTHC_O); - switch (instr.othc.func) { - case LIT_F: - sprintf(buf, "%s, %hd, %hd", regname_get(instr.othc.reg), - instr.othc.offset, instr.othc.arg); - break; - case ARI_F: case SRI_F: - sprintf(buf, "%s, %hd", regname_get(instr.othc.reg), - instr.othc.arg); - break; - case MUL_F: case DIV_F: case CFHI_F: case CFLO_F: case JMP_F: - case CSI_F: - sprintf(buf, "%s, %hd", regname_get(instr.othc.reg), - instr.othc.offset); - break; - case SLL_F: case SRL_F: - sprintf(buf, "%s, %hd, %hu", regname_get(instr.othc.reg), - instr.othc.offset, instr.othc.arg); - break; - case JREL_F: - sprintf(buf, "%hd\t%s", instr.othc.arg, - instruction_formAddress_comment(addr, - addr+instr.othc.arg)); - break; - default: - bail_with_error("Unknown other computational instruction function (%d)!", - instr.comp.func); - break; - } - break; - case immed_instr_type: - switch (instr.immed.op) { - case ADDI_O: - sprintf(buf, "%s, %hd, %hd", regname_get(instr.immed.reg), - instr.immed.offset, instr.immed.immed); - break; - case ANDI_O: case BORI_O: case NORI_O: case XORI_O: - sprintf(buf, "%s, %hd, 0x%hx", regname_get(instr.immed.reg), - instr.immed.offset, instr.immed.immed); - break; - case BEQ_O: case BGEZ_O: case BGTZ_O: - case BLEZ_O: case BLTZ_O: case BNE_O: - sprintf(buf, "%s, %hd, %hd\t%s", regname_get(instr.immed.reg), - instr.immed.offset, instr.immed.immed, - instruction_formAddress_comment(addr, - addr+instr.immed.immed)); - break; - default: - bail_with_error("Unknown immediate type instruction opcode (%d)!", - instr.immed.op); - break; - } - break; - case jump_instr_type: - switch (instr.jump.op) { - case JMPA_O: case CALL_O: - sprintf(buf, "%u\t%s", instr.jump.addr, - instruction_formAddress_comment(addr, instr.jump.addr)); - break; - case RTN_O: - // no arguments in this case - break; - default: - bail_with_error("Unknown jump type instruction opcode (%d)!", - instr.jump.op); - break; - } - break; - case syscall_instr_type: - switch (instr.syscall.code) { - case exit_sc: - sprintf(buf, "%hd", instr.syscall.offset); - break; - case print_str_sc: case print_int_sc: - case print_char_sc: case read_char_sc: - sprintf(buf, "%s, %hd", regname_get(instr.syscall.reg), - instr.syscall.offset); - break; - case start_tracing_sc: case stop_tracing_sc: - // no arguments, so nothing to do! - break; - } - break; - default: - bail_with_error("Unknown instruction type (%d) in instruction_assembly_form!", - it); - break; - } - - return instr_buf; -} - -// Requires: out is open and writable FILE -// print the header of the instruction output table on out -void instruction_print_table_heading(FILE *out) { - fprintf(out, "%s %s\n", "Address", "Instruction"); -} - -// Requires: out is an open FILE, and instr is found at address addr. -// Print addr on out, ": ", then the instruction's symbolic -// (assembly language) form, and finally a newline character (all on one line) -void instruction_print(FILE *out, address_type addr, bin_instr_t instr) { - fprintf(out, "%8u: %s\n", addr, instruction_assembly_form(addr, instr)); -} - -// Return the mnemonic for the given system call code -const char *instruction_syscall_mnemonic(syscall_type code) -{ - switch (code) { - case exit_sc: - return "EXIT"; - break; - case print_str_sc: - return "PSTR"; - break; - case print_int_sc: - return "PINT"; - break; - case print_char_sc: - return "PCH"; - break; - case read_char_sc: - return "RCH"; - break; - case start_tracing_sc: - return "STRA"; - break; - case stop_tracing_sc: - return "NOTR"; - break; - default: - bail_with_error("Unknown code (%u) in instruction_syscall_mnemonic", - code); - return "NEVERHAPPENS"; - break; - } -} - -// Requires: instr is a SYSCALL instruction -// (i.e., instr.syscall.op == OTHC_O and instr.syscall.func == SYS_F). -// Return the code field that tells what kind of system call is being made -syscall_type instruction_syscall_number(bin_instr_t instr) { - assert(instr.syscall.op == OTHC_O && instr.syscall.func == SYS_F); - return instr.syscall.code; -} - -// Requires: bi is a computational instruction (bi.comp.op == COMP_O). -// Return a string giving the assembly language mnemonic for bi's operation -const char *instruction_compFunc2name(bin_instr_t bi) { - assert(bi.comp.op == COMP_O); - switch (bi.comp.func) { - case NOP_F: - return "NOP"; - break; - case ADD_F: - return "ADD"; - break; - case SUB_F: - return "SUB"; - break; - case CPW_F: - return "CPW"; - break; - case CPR_F: - return "CPR"; - break; - case AND_F: - return "AND"; - break; - case BOR_F: - return "BOR"; - break; - case NOR_F: - return "NOR"; - break; - case XOR_F: - return "XOR"; - break; - case LWR_F: - return "LWR"; - break; - case SWR_F: - return "SWR"; - break; - case SCA_F: - return "SCA"; - break; - case LWI_F: - return "LWI"; - break; - case NEG_F: - return "NEG"; - break; - default: - bail_with_error("Unknown function code (%d) in instruction_compFunc2name", - bi.comp.func); - break; - } - return NULL; // should never happen -} - -// Requires: bi is an other computational instruction (bi.othc.op == OTHC_O). -// Return a string giving the assembly language mnemonic for bi's operation -const char *instruction_otherCompFunc2name(bin_instr_t bi) { - assert(bi.othc.op == OTHC_O); - switch (bi.othc.func) { - case LIT_F: - return "LIT"; - break; - case ARI_F: - return "ARI"; - break; - case SRI_F: - return "SRI"; - break; - case MUL_F: - return "MUL"; - break; - case DIV_F: - return "DIV"; - break; - case CFHI_F: - return "CFHI"; - break; - case CFLO_F: - return "CFLO"; - break; - case SLL_F: - return "SLL"; - break; - case SRL_F: - return "SRL"; - break; - case JMP_F: - return "JMP"; - break; - case CSI_F: - return "CSI"; - break; - case JREL_F: - return "JREL"; - break; - case SYS_F: - return instruction_syscall_mnemonic(instruction_syscall_number(bi)); - break; - default: - bail_with_error("Unknown function code (%d) in instruction_otherCompFunc2name", - bi.comp.func); - break; - } - return NULL; // should never happen -} - -// Requires: toknum is the token number of a system call operation -// Return the system call type corresponding to the given token number -syscall_type instruction_token2SyscallCode(int toknum) -{ - switch (toknum) { - case exitopsym: - return exit_sc; - break; - case pstropsym: - return print_str_sc; - break; - case pintopsym: - return print_int_sc; - break; - case pchopsym: - return print_char_sc; - break; - case rchopsym: - return read_char_sc; - break; - case straopsym: - return start_tracing_sc; - break; - case notropsym: - return stop_tracing_sc; - break; - default: - bail_with_error("Unknown token type in instruction_token2SyscallCode: %d", - toknum); - return 0; // should never happen - break; - } -} diff --git a/vm/instruction.h b/vm/instruction.h deleted file mode 100755 index 5993fa3..0000000 --- a/vm/instruction.h +++ /dev/null @@ -1,181 +0,0 @@ -// $Id: instruction.h,v 1.40 2024/11/10 14:34:25 leavens Exp $ -#ifndef _INSTRUCTION_H -#define _INSTRUCTION_H -#include -#include -#include "machine_types.h" -#include "bof.h" - -// op codes in binary instructions for the SSM -typedef enum {COMP_O = 0, OTHC_O = 1, ADDI_O = 2, ANDI_O = 3, BORI_O = 4, - NORI_O = 5, XORI_O = 6, - BEQ_O = 7, BGEZ_O = 8, BGTZ_O = 9, BLEZ_O = 10, BLTZ_O = 11, - BNE_O = 12, JMPA_O = 13, CALL_O = 14, RTN_O = 15 - } op_code; - -// function codes in binary instructions for the SSM (when opcode is 0) -typedef enum {NOP_F = 0, ADD_F = 1, SUB_F = 2, CPW_F = 3, CPR_F = 4, - AND_F = 5, BOR_F = 6, NOR_F = 7, XOR_F = 8, - LWR_F = 9, SWR_F = 10, SCA_F = 11, LWI_F = 12, NEG_F = 13 - } func0_code; - -// function codes in binary instructions for the SSM (when opcode is 1) -typedef enum {LIT_F = 1, ARI_F = 2, SRI_F = 3, MUL_F = 4, DIV_F = 5, - CFHI_F = 6, CFLO_F = 7, SLL_F = 8, SRL_F = 9, JMP_F = 10, - CSI_F = 11, JREL_F = 12, SYS_F = 15 - } func1_code; - -// instruction types (each is a binary instruction format) -typedef enum {comp_instr_type, other_comp_instr_type, - immed_instr_type, jump_instr_type, syscall_instr_type, - error_instr_type - } instr_type; - -// system calls -typedef enum {exit_sc = 1, print_str_sc = 2, print_int_sc = 3, - print_char_sc = 4, read_char_sc = 5, - start_tracing_sc = 2046, stop_tracing_sc = 2047 -} syscall_type; - -// computational type instructions, with opcode 0 -typedef struct { - opcode_type op : 4; - reg_num_type rt : 3; // target register - offset_type ot : 9; // offset from target register - reg_num_type rs : 3; // source register - offset_type os : 9; // offset from source register - func_type func : 4; -} comp_instr_t; - -// other computational type instructions, with opcode 1, except system calls -typedef struct { - opcode_type op : 4; - reg_num_type reg : 3; - offset_type offset : 9; - arg_type arg : 12; - func_type func : 4; -} other_comp_instr_t; - -// system call instructions, with op field 1 and func field 15 -typedef struct { - opcode_type op : 4; - reg_num_type reg : 3; - offset_type offset : 9; - syscall_type code : 12; - func_type func : 4; -} syscall_instr_t; - -// immediate operand type instructions -// with signed immediate operands -typedef struct { - opcode_type op : 4; - reg_num_type reg : 3; - offset_type offset : 9; - immediate_type immed : 16; -} immed_instr_t; - -// immediate operand type instructions -// with unsigned immediate operands -typedef struct { - opcode_type op : 4; - reg_num_type reg : 3; - offset_type offset : 9; - uimmed_type uimmed : 16; -} uimmed_instr_t; - -// jump type instructions -typedef struct { - opcode_type op : 4; - address_type addr : 28; -} jump_instr_t; - -// binary instructions of any type -typedef union { - comp_instr_t comp; - other_comp_instr_t othc; - syscall_instr_t syscall; - immed_instr_t immed; - uimmed_instr_t uimmed; - jump_instr_t jump; -} bin_instr_t; - -// Return the type of the binary instruction given -extern instr_type instruction_type(bin_instr_t i); - -// Requires: bof is open for reading in binary -// Read a single instruction (in binary) from bf and return it, -// but exit with an error if there is a problem. -extern bin_instr_t instruction_read(BOFFILE bf); - -// Requires: bof is open for writing in binary -// Write the binary instruction bi to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_bin_instr(BOFFILE bf, bin_instr_t bi); - -// Requires: bof is open for writing in binary -// Write the computational instruction oci to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_compInstr(BOFFILE bf, comp_instr_t oci); - -// Requires: bof is open for writing in binary -// Write the other computational instruction oci to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_otherCompInstr(BOFFILE bf, other_comp_instr_t oci); - -// Requires: bof is open for writing in binary -// Write the system instruction si to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_syscallInstr(BOFFILE bf, syscall_instr_t si); - -// Requires: bof is open for writing in binary -// Write the immediate instruction ii with opcode op to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_immedInstr(BOFFILE bf, immed_instr_t ii); - -// Requires: bof is open for writing in binary -// Write the immediate instruction ii with opcode op to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_uimmedInstr(BOFFILE bf, uimmed_instr_t ii); - -// Requires: bof is open for writing in binary -// Write the jump instruction ji with opcode op to bf in binary, -// but exit with an error if there is a problem. -extern void instruction_write_jumpInstr(BOFFILE bf, jump_instr_t ji); - -// Return the assembly language name (mnemonic) for bi -extern const char *instruction_mnemonic(bin_instr_t bi); - -// Return a string containing the assembly language form of instr, -// which is found at address addr -extern const char *instruction_assembly_form(address_type addr, - bin_instr_t instr); - -// Requires: out is open and writable FILE -// print the header of the instruction output table on out -extern void instruction_print_table_heading(FILE *out); - -// Requires: out is an open FILE, and instr is found at address addr. -// Print addr on out, ": ", then the instruction's symbolic -// (assembly language) form, and finally a newline character (all on one line) -extern void instruction_print(FILE *out, address_type addr, bin_instr_t instr); - -// Return the mnemonic for the given system call code -extern const char *instruction_syscall_mnemonic(unsigned int code); - -// Requires: instr is a SYSCALL instruction -// (i.e., instr.syscall.op == OTHC_O and instr.syscall.func == SYS_F). -// Return the code field that tells what kind of system call is being made -extern syscall_type instruction_syscall_number(bin_instr_t instr); - -// Requires: bi is a computational instruction (bi.comp.op == COMP_O). -// Return a string giving the assembly language mnemonic for bi's operation -extern const char *instruction_compFunc2name(bin_instr_t bi); - -// Requires: bi is an other computational instruction (bi.othc.op == OTHC_O). -// Return a string giving the assembly language mnemonic for bi's operation -extern const char *instruction_otherCompFunc2name(bin_instr_t bi); - -// Return the system call type corresponding to the given token number -extern syscall_type instruction_token2SyscallCode(int toknum); - -#endif diff --git a/vm/lexer.c b/vm/lexer.c deleted file mode 100755 index 7525c07..0000000 --- a/vm/lexer.c +++ /dev/null @@ -1,230 +0,0 @@ -/* $Id: lexer.c,v 1.27 2024/11/10 14:34:25 leavens Exp $ */ -#include -#include -#include -#include -#include -#include -#include "ast.h" -#include "parser_types.h" -#include "lexer.h" -#include "machine_types.h" -#include "utilities.h" - - -// All of the other lexer_* functions declared in lexer.h -// that are not defined here -// are defined in asm_lexer.l's user code section. - - -// Requires: toknum is a token number (from asm.tab.h) -// of an instruction -// Return the opcode corresponding to the given opcode token number -op_code lexer_token2opcode(int toknum) -{ - op_code ret; - - switch (toknum) { - // register type op codes - case noopsym: case addopsym: case subopsym: case cpwopsym: case cpropsym: - case andopsym: case boropsym: case noropsym: case xoropsym: - case lwropsym: case swropsym: case scaopsym: case lwiopsym: - case negopsym: - ret = COMP_O; - break; - case litopsym: case ariopsym: case sriopsym: - case mulopsym: case divopsym: case cfhiopsym: case cfloopsym: - case sllopsym: case srlopsym: case jmpopsym: case csiopsym: - case jrelopsym: - ret = OTHC_O; - break; - // system call op codes - case exitopsym: case pstropsym: case pintopsym: - case pchopsym: case rchopsym: case straopsym: case notropsym: - ret = OTHC_O; // opcode is OTHC_O for these - break; - // immedidate format op codes - case addiopsym: - ret = ADDI_O; - break; - case andiopsym: - ret = ANDI_O; - break; - case boriopsym: - ret = BORI_O; - break; - case noriopsym: - ret = NORI_O; - break; - case xoriopsym: - ret = XORI_O; - break; - case beqopsym: - ret = BEQ_O; - break; - case bgezopsym: - ret = BGEZ_O; - break; - case bgtzopsym: - ret = BGTZ_O; - break; - case blezopsym: - ret = BLEZ_O; - break; - case bltzopsym: - ret = BLTZ_O; - break; - case bneopsym: - ret = BNE_O; - break; - // jump format instructions - case jmpaopsym: - ret = JMPA_O; - break; - case callopsym: - ret = CALL_O; - break; - case rtnopsym: - ret = RTN_O; - break; - default: - bail_with_error("Token number not of an op code (%d) in lexer_token2opcode!", - toknum); - break; - } - return ret; -} - -// Requires: toknum is a token number (from asm.tab.h) -// that corresponds to a computational instruction -// or an other computational instruction -// Return the function code corresponding to the given opcode token number -func_type lexer_token2func(int toknum) -{ - func_type ret; - - switch (toknum) { - case noopsym: - ret = NOP_F; - break; - case addopsym: - ret = ADD_F; - break; - case subopsym: - ret = SUB_F; - break; - case cpwopsym: - ret = CPW_F; - break; - case cpropsym: - ret = CPR_F; - break; - case andopsym: - ret = AND_F; - break; - case boropsym: - ret = BOR_F; - break; - case noropsym: - ret = NOR_F; - break; - case xoropsym: - ret = XOR_F; - break; - case lwropsym: - ret = LWR_F; - break; - case swropsym: - ret = SWR_F; - break; - case scaopsym: - ret = SCA_F; - break; - case lwiopsym: - ret = LWI_F; - break; - case negopsym: - ret = NEG_F; - break; - case litopsym: - ret = LIT_F; - break; - case ariopsym: - ret = ARI_F; - break; - case sriopsym: - ret = SRI_F; - break; - case mulopsym: - ret = MUL_F; - break; - case divopsym: - ret = DIV_F; - break; - case cfhiopsym: - ret = CFHI_F; - break; - case cfloopsym: - ret = CFLO_F; - break; - case sllopsym: - ret = SLL_F; - break; - case srlopsym: - ret = SRL_F; - break; - case jmpopsym: - ret = JMP_F; - break; - case csiopsym: - ret = CSI_F; - break; - case jrelopsym: - ret = JREL_F; - break; - case exitopsym: case pstropsym: case pintopsym: case pchopsym: - case rchopsym: case straopsym: case notropsym: - ret = SYS_F; - break; - default: - bail_with_error("Unhandled token (%d) in lexer_token2func", toknum); - break; - } - return ret; -} - -// Requires: toknum is a token number (from asm.tab.h) -// that corresponds to a system call instruction -// Return the system call code that corresponds to that token -syscall_type lexer_token2syscall_code(int toknum) -{ - syscall_type ret; - switch (toknum) { - case exitopsym: - ret = exit_sc; - break; - case pstropsym: - ret = print_str_sc; - break; - case pintopsym: - ret = print_int_sc; - break; - case pchopsym: - ret = print_char_sc; - break; - case rchopsym: - ret = read_char_sc; - break; - case straopsym: - ret = start_tracing_sc; - break; - case notropsym: - ret = stop_tracing_sc; - break; - default: - bail_with_error("Unknown token (%d) given to lexer_token2syscall_code!", - toknum); - ret = 0; - } - return ret; -} diff --git a/vm/lexer.h b/vm/lexer.h deleted file mode 100755 index bf4b3f5..0000000 --- a/vm/lexer.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $Id: lexer.h,v 1.9 2024/07/15 20:31:49 leavens Exp $ */ -#ifndef _LEXER_H -#define _LEXER_H -#include -#include -#include "ast.h" -#include "parser_types.h" -#include "asm.tab.h" -#include "instruction.h" - -// Have any error messages been printed? -extern bool errors_noted; - -// The current input file -// extern FILE *yyin; -// The input line number of the current or next input line -// extern int yylineno; -// The value of the current token -// extern YYSTYPE yylval; - -// Requires: fname != NULL -// Requires: fname is the name of a readable file -// Initialize the lexer and start it reading -// from the given file name -extern void lexer_init(char *fname); - -// Return the next token in the input -extern int yylex(); - -// Return the name of the current file -extern const char *lexer_filename(); - -// Return the line number of the next token -extern unsigned int lexer_line(); - -// On standard output: -// Print a message about the file name of the lexer's input -// and then print a heading for the lexer's output. -extern void lexer_print_output_header(); - -// Print information about the token t to stdout -// followed by a newline -extern void lexer_print_token(int t, unsigned int tline, - const char *txt); - -// On standard output, print each token -// using the format in lexer_print_token -extern void lexer_output(); - -// Requires: toknum is a token number (from asm.tab.h) -// of an instruction -// Return the opcode corresponding to the given opcode token number -extern op_code lexer_token2opcode(int toknum); - -// Return the function code corresponding to the given opcode token number -extern func_type lexer_token2func(int toknum); - -// Requires: toknum is a token number (from asm.tab.h) -// that corresponds to a system call instruction -// Return the system call code that corresponds to that token -extern syscall_type lexer_token2syscall_code(int toknum); - -#endif diff --git a/vm/lexer_error1.asm b/vm/lexer_error1.asm deleted file mode 100755 index 1a5d750..0000000 --- a/vm/lexer_error1.asm +++ /dev/null @@ -1,8 +0,0 @@ - # $Id: lexer_error1.asm,v 1.2 2024/08/28 21:25:00 leavens Exp $ -.text 0 - CFHI $8, 2 # error, register number can't be 8 or higher - CFLO $13, 0 # error, again, register number can't be 13 -.data 2048 -.stack 4096 -.end - diff --git a/vm/lexer_main.c b/vm/lexer_main.c deleted file mode 100755 index fbaadfe..0000000 --- a/vm/lexer_main.c +++ /dev/null @@ -1,26 +0,0 @@ -// $Id: lexer_main.c,v 1.2 2023/09/06 22:43:06 leavens Exp $ -#include -#include -#include "ast.h" -#include "parser_types.h" -#include "lexer.h" -#include "utilities.h" - -void usage(const char *cmdname) { - bail_with_error("Usage: %s file.asm", cmdname); - exit(EXIT_FAILURE); -} - -int main(int argc, char *argv[]) { - const char *cmdname = argv[0]; - argc--; - argv++; - if (argc != 1 || argv[0][0] == '-') { - // must be a file name and no options allowed! - usage(cmdname); - } - - lexer_init(argv[0]); - lexer_output(); - return EXIT_SUCCESS; -} diff --git a/vm/lexer_test1.asm b/vm/lexer_test1.asm deleted file mode 100755 index cf0e993..0000000 --- a/vm/lexer_test1.asm +++ /dev/null @@ -1,61 +0,0 @@ - # $Id: lexer_test1.asm,v 1.22 2024/11/10 14:34:25 leavens Exp leavens $ - -.text 0 - - NOP - SRI $sp, 1 - ADD $sp, 0, $0, +1 - SUB $gp, 1, $sp, 0 # put 0 in memory[GP+1] - CPW $gp, 3, $sp, 0 # put 99 in top of stack - CPR $gp, $gp - AND $sp, -1, $r4, 0 # anding memory[SP] and location 1, result in memory[SP-1]! - BOR $sp, -1, $r4, 0 # or location zero, which is 0, so no change - NOR $sp, -1, $sp, -1 # bitwise negate memory[SP-1] - XOR $gp, 2, $gp, 15 # xor c and memory[GP+15] - LWR $r4, $gp, 2 - SWR $gp, 4, $r4 - SCA $sp, -1, $sp, 0 # store stack top address one below stack top - NEG $gp, 0, $gp, 0 - LIT $sp, -1, 122 # put 122 below top of the stack - SRI $sp, 1 # stack top is 122 - MUL $sp, 0 - CFLO $sp, -1 - CFHI $sp, -2 - DIV $sp, 0 # will cause a division by 0 error, eventually! - CFLO $sp, -3 - CFHI $sp, -4 - SLL $sp, 0, 2 - SRL $sp, -1, 3 - JREL +2 # skip next instruction - JMP $r5, 0 # causes a segmentation fault! - ANDI $sp, 0, 0x0123 - BORI $sp, -1, 0x003f - NORI $sp, -2, 0x1ff - XORI $sp, -3, 0 - BEQ $sp, 0, +2 # skip next instruction - BGEZ $sp, -2, +2 - BGTZ $sp, -3, -0xf # jump -15 backwards, if memory[GPR[$sp]-3] > 0 - BLTZ $sp, -4, +2 - BLEZ $sp, -5, +2 - SCA $sp, -6, $gp, 0 - LWI $sp, -7, $sp, -6 # should load memory[GPR[$gp]] - BNE $sp, -1, -4 - JMPA here - CALL here - JREL +2 -here: RTN - PSTR $gp, 4 - PCH $gp, 15 - RCH $gp, 5 - NOTR - EXIT 1 - -.data 2048 - WORD b = 10 - STRING[2] str = "1234" - CHAR c = 'c' - STRING[1] three = "3\n" - WORD sixteen = 0x10 - -.stack 8096 -.end diff --git a/vm/lexer_test1.lst b/vm/lexer_test1.lst deleted file mode 100755 index 08776ef..0000000 --- a/vm/lexer_test1.lst +++ /dev/null @@ -1,50 +0,0 @@ -Address Instruction - 0: NOP - 1: SRI $sp, 1 - 2: ADD $sp, 0, $gp, 1 - 3: SUB $gp, 1, $sp, 0 - 4: CPW $gp, 3, $sp, 0 - 5: CPR $gp, $gp - 6: AND $sp, -1, $r4, 0 - 7: BOR $sp, -1, $r4, 0 - 8: NOR $sp, -1, $sp, -1 - 9: XOR $gp, 2, $gp, 15 - 10: LWR $r4, $gp, 2 - 11: SWR $gp, 4, $r4 - 12: SCA $sp, -1, $sp, 0 - 13: NEG $gp, 0, $gp, 0 - 14: LIT $sp, -1, 122 - 15: SRI $sp, 1 - 16: MUL $sp, 0 - 17: CFLO $sp, -1 - 18: CFHI $sp, -2 - 19: DIV $sp, 0 - 20: CFLO $sp, -3 - 21: CFHI $sp, -4 - 22: SLL $sp, 0, 2 - 23: SRL $sp, -1, 3 - 24: JREL 2 # target is word address 26 - 25: JMP $r5, 0 - 26: ANDI $sp, 0, 0x123 - 27: BORI $sp, -1, 0x3f - 28: XORI $sp, -2, 0x1ff - 29: XORI $sp, -3, 0x0 - 30: BEQ $sp, 0, 2 # target is word address 32 - 31: BGEZ $sp, -2, 2 # target is word address 33 - 32: BGTZ $sp, -3, -15 # target is word address 17 - 33: BLTZ $sp, -4, 2 # target is word address 35 - 34: BLEZ $sp, -5, 2 # target is word address 36 - 35: SCA $sp, -6, $gp, 0 - 36: LWI $sp, -7, $sp, -6 - 37: BNE $sp, -1, -4 # target is word address 33 - 38: JMPA 41 # target is word address 41 - 39: CALL 41 # target is word address 41 - 40: JREL 2 # target is word address 42 - 41: RTN - 42: PSTR $gp, 4 - 43: PCH $gp, 15 - 44: RCH $gp, 5 - 45: NOTR - 46: EXIT 1 - 2048: 10 2049: 875770417 2050: 0 2051: 99 2052: 2611 - 2053: 16 2054: 0 ... diff --git a/vm/lexer_test2.asm b/vm/lexer_test2.asm deleted file mode 100755 index 286a37c..0000000 --- a/vm/lexer_test2.asm +++ /dev/null @@ -1,33 +0,0 @@ - # $Id: lexer_test2.asm,v 1.8 2024/08/20 19:25:40 leavens Exp $ - .text go - NOTR - PSTR $gp, 18 - EXIT 1 -go: EXIT 0 - .data 100 - WORD sixteen = 0x10 - CHAR c = 'a' - CHAR tab = '\t' - CHAR nl = '\n' - CHAR SQ = '\'' - CHAR DQ = '\"' - CHAR BS = '\\' - CHAR R = '\r' - CHAR FF = '\f' - CHAR VT = '\v' - CHAR BELL = '\a' - CHAR HE2 = '\x0F' - CHAR h = '\x1' - CHAR h12 = '\x12' - CHAR he = '\xf' - CHAR sb = '\b' - CHAR null = '\0' - CHAR oe = '\0135' - STRING [1] ot3 = "no\n" - STRING [3] others = "\r\f\v\a\b\'\"\n" - STRING [2] wnl = "abc12\n" - STRING [1] he2 = "a\x12\x0f" - STRING [12] othersE = "\r\f\v\a\b\'\"\x0F\0127\n" - .stack 0x4000 - .end - diff --git a/vm/lexer_test2.lst b/vm/lexer_test2.lst deleted file mode 100755 index 234fed9..0000000 --- a/vm/lexer_test2.lst +++ /dev/null @@ -1,12 +0,0 @@ -Address Instruction - 0: NOTR - 1: PSTR $gp, 18 - 2: EXIT 1 - 3: EXIT 0 - 100: 16 101: 97 102: 9 103: 10 104: 39 - 105: 34 106: 92 107: 13 108: 12 109: 11 - 110: 7 111: 15 112: 1 113: 18 114: 15 - 115: 8 116: 0 117: 93 118: 683886 119: 118164493 - 120: 170010376 121: 0 122: 828596833 123: 2610 - 124: 987745 125: 118164493 126: 253896456 127: 2647 - 128: 0 ... diff --git a/vm/lexer_test3.asm b/vm/lexer_test3.asm deleted file mode 100755 index 90dccae..0000000 --- a/vm/lexer_test3.asm +++ /dev/null @@ -1,11 +0,0 @@ - # $Id: lexer_test3.asm,v 1.4 2024/07/26 16:19:50 leavens Exp $ - .text go -go: ADDI $sp, 0, 93 - ADDI $sp, 0, 093 - ADDI $sp, 0, -093 - EXIT 0 - .data 512 - WORD sixteen = 0x10 - .stack 4512 - .end - diff --git a/vm/lexer_test3.lst b/vm/lexer_test3.lst deleted file mode 100755 index 2f942a3..0000000 --- a/vm/lexer_test3.lst +++ /dev/null @@ -1,6 +0,0 @@ -Address Instruction - 0: ADDI $sp, 0, 93 - 1: ADDI $sp, 0, 93 - 2: ADDI $sp, 0, -93 - 3: EXIT 0 - 512: 16 513: 0 ... diff --git a/vm/lexer_test4.asm b/vm/lexer_test4.asm deleted file mode 100755 index 161d179..0000000 --- a/vm/lexer_test4.asm +++ /dev/null @@ -1,9 +0,0 @@ - # $Id: lexer_test4.asm,v 1.1 2024/08/20 02:21:19 leavens Exp $ - .text 0 - LIT $sp, -1, 122 # put 122 below top of the stack - SRI $sp, 1 # stack top is 122 - MUL $sp, 0 - EXIT 0 -.data 1024 -.stack 2048 -.end diff --git a/vm/lexer_test4.lst b/vm/lexer_test4.lst deleted file mode 100755 index 728c82c..0000000 --- a/vm/lexer_test4.lst +++ /dev/null @@ -1,6 +0,0 @@ -Address Instruction - 0: LIT $sp, -1, 122 - 1: SRI $sp, 1 - 2: MUL $sp, 0 - 3: EXIT 0 - 1024: 0 ... diff --git a/vm/lexer_test5.asm b/vm/lexer_test5.asm deleted file mode 100755 index 4b82e91..0000000 --- a/vm/lexer_test5.asm +++ /dev/null @@ -1,10 +0,0 @@ - # $Id: lexer_test5.asm,v 1.1 2024/08/22 00:44:21 leavens Exp $ - .text 0 - LIT $sp, 0, -1 - ANDI $sp, 0, 0xff - ADDI $sp, 0, 0x100 - EXIT 0 - .data 512 - STRING [3] ls = "a long str\n" - .stack 1024 - .end diff --git a/vm/lexer_test5.lst b/vm/lexer_test5.lst deleted file mode 100755 index 635ce13..0000000 --- a/vm/lexer_test5.lst +++ /dev/null @@ -1,7 +0,0 @@ -Address Instruction - 0: LIT $sp, 0, -1 - 1: ANDI $sp, 0, 0xff - 2: ADDI $sp, 0, 256 - 3: EXIT 0 - 512: 1869357153 513: 1931503470 514: 684660 515: 0 - ... diff --git a/vm/lexer_test6.asm b/vm/lexer_test6.asm deleted file mode 100755 index 5f16db2..0000000 --- a/vm/lexer_test6.asm +++ /dev/null @@ -1,10 +0,0 @@ - # $Id: lexer_test6.asm,v 1.4 2024/07/26 16:19:50 leavens Exp $ - .text st_art -st_art: SWR $sp, 0, $sp - ADDI $sp, 0, -1 - LWR $sp, $sp, 0 - EXIT 0 - .data 1024 - .stack 4096 - .end - diff --git a/vm/lexer_test6.lst b/vm/lexer_test6.lst deleted file mode 100755 index 058104b..0000000 --- a/vm/lexer_test6.lst +++ /dev/null @@ -1,6 +0,0 @@ -Address Instruction - 0: SWR $sp, 0, $sp - 1: ADDI $sp, 0, -1 - 2: LWR $sp, $sp, 0 - 3: EXIT 0 - 1024: 0 ... diff --git a/vm/lexer_utilities.c b/vm/lexer_utilities.c deleted file mode 100755 index 6979f86..0000000 --- a/vm/lexer_utilities.c +++ /dev/null @@ -1,21 +0,0 @@ -/* $Id: lexer_utilities.c,v 1.1 2023/11/13 18:26:52 leavens Exp $ */ -#include -#include -#include -#include "lexer_utilities.h" - -#define BUF_SIZE 1024 - -// Call yyerror to print an error message on stderr -// starting with the filename, ":", the lexer's current line number, ": ", -// and then the formatted message (as in sprintf) -extern void formatted_yyerror(const char *filename, const char *fmt, ...) -{ - fflush(stdout); // flush so output comes after what has happened already - char buf[BUF_SIZE]; - va_list(args); - va_start(args, fmt); - vsnprintf(buf, BUF_SIZE, fmt, args); - yyerror(filename, buf); - va_end(args); -} diff --git a/vm/lexer_utilities.h b/vm/lexer_utilities.h deleted file mode 100755 index ecc4be0..0000000 --- a/vm/lexer_utilities.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: lexer_utilities.h,v 1.1 2023/11/13 18:26:52 leavens Exp $ */ -#ifndef _LEXER_UTILITIES_H -#define _LEXER_UTILITIES_H - -// Report a syntax error on the current line on stderr. -// The output looks like: the filename, ":", the lexer's current line number, -// ": ", and then msg. -extern void yyerror(const char *filename, const char *msg); - -// Call yyerror to print an error message on stderr -// starting with the filename, ":", the lexer's current line number, ": ", -// and then the formatted message (as in sprintf) -extern void formatted_yyerror(const char *filename, const char *fmt, ...); - -#endif diff --git a/vm/machine.c b/vm/machine.c deleted file mode 100755 index a6d3866..0000000 --- a/vm/machine.c +++ /dev/null @@ -1,649 +0,0 @@ -/* $Id: machine.c,v 1.49 2024/11/10 22:47:50 leavens Exp leavens $ */ -#include -#include -#include -#include -#include "machine_types.h" -#include "machine.h" -#include "regname.h" -#include "utilities.h" - -#define MAX_PRINT_WIDTH 59 - -// the VM's memory, in signed and unsigned word and binary instruction views. -static union mem_u { - word_type words[MEMORY_SIZE_IN_WORDS]; - uword_type uwords[MEMORY_SIZE_IN_WORDS]; - bin_instr_t instrs[MEMORY_SIZE_IN_WORDS]; -} memory; - -// general purpose registers -static word_type GPR[NUM_REGISTERS]; -// hi and lo registers used in multiplication and division. -// A view as a (signed) long int (result, 64 bits) -// and as an array (hilo) of 2 32-bit ints. -static union longAs2words_u { - long result; - word_type hilo[2]; -} hilo_regs; - -// LO is index 0, HI is index 1, for an x86 architecture -// (because the x86 is little-endian) -#define LO 0 -#define HI 1 - -// the program counter -static address_type PC; - -// should the machine be printing tracing output? -static bool tracing; - -// initial_stack_bottom is used for tracing -static address_type initial_stack_bottom; - -// words of instructions (based on the header) -static unsigned short instruction_words; -// words of global data (based on the header) -static unsigned short global_data_words; - - -// should the machine be running? (default true) -static bool running; - -// set up the state of the machine -static void initialize() -{ - tracing = true; // default for tracing - instruction_words = 0; - global_data_words = 0; - running = true; - - // zero the registers - for (int j = 0; j < NUM_REGISTERS; j++) { - GPR[j] = 0; - } - hilo_regs.result = 0; - // zero out the memory - for (int i = 0; i < MEMORY_SIZE_IN_WORDS; i++) { - memory.words[i] = 0; - } -} - -// Requires: bf is a binary object file that is open for reading -// Load count instructions from bf into the memory starting at address 0. -// If any errors are encountered, exit with an error message. -static void load_instructions(BOFFILE bf, int count) -{ - for (int wa = 0; wa < count; wa++) { - memory.instrs[wa] = instruction_read(bf); - } -} - -// Requires: bf is a binary object file that is open for reading -// Load count words from bf into the memory -// starting at word address global_base. -// If any errors are encountered, exit with an error message. -static void load_data(BOFFILE bf, int count, unsigned int global_base) -{ - for (int wo = 0; wo < count; wo++) { - memory.words[global_base+wo] = bof_read_word(bf); - } -} - -// Requires: bf is open for reading in binary -// Load the binary object file bf, and get ready to run it -void machine_load(BOFFILE bf) -{ - initialize(); - - // read and check the header - BOFHeader bh = bof_read_header(bf); - if (bh.text_length >= bh.data_start_address) { - bail_with_error("%s (%u) %s (%u)!", - "Text, i.e., program length", bh.text_length, - "is not less than the start address of the global data", - bh.data_start_address); - } - if (bh.data_start_address + bh.data_length >= bh.stack_bottom_addr) { - bail_with_error("%s (%u) + %s (%u) %s (%u)!", - "Global data start address", bh.data_start_address, - "global data length", bh.data_length, - "is not less than the stack bottom address", - bh.stack_bottom_addr); - } - if (bh.stack_bottom_addr >= MEMORY_SIZE_IN_WORDS) { - bail_with_error("%s (%u) %s (%u)!", - "stack_bottom_addr", bh.stack_bottom_addr, - "is not less than the memory size", - MEMORY_SIZE_IN_WORDS); - } - - // load the program - instruction_words = bh.text_length; - load_instructions(bf, instruction_words); - - global_data_words = bh.data_length; - - load_data(bf, global_data_words, bh.data_start_address); - - // initialize the registers - PC = bh.text_start_address; - - GPR[GP] = bh.data_start_address; - GPR[SP] = bh.stack_bottom_addr; - GPR[FP] = bh.stack_bottom_addr; - initial_stack_bottom = bh.stack_bottom_addr; -} - -// Requires: fmt == 'x' or fmt == 'd' -// print the memory location at word address wa to out -// with a format determined by fmt and no newline, -// returns the number of characters written -static int print_loc(FILE *out, address_type wa, char fmt) -{ - int count; - if (fmt == 'x') { - count = fprintf(out, "%8d: 0x%x\t", wa, - memory.words[wa]); - } else { // fmt == 'd' - count = fprintf(out, "%8d: %d\t", wa, - memory.words[wa]); - } - return count; -} - -// print the word address given and the instruction's assembly form -static void print_instruction(FILE *out, address_type wa, bin_instr_t bi) -{ - fprintf(out, "%6d: %s\n", wa, instruction_assembly_form(wa, bi)); -} - -// Print the word memory in hex or decimal based on the fmt argument -// between the word addresses start (inclusive) and end (inclusive) to out, -// without a newline and eliding all repeated zeros in the range -// Returns true if printed a newline at the end, false otherwise -static bool print_memory_nonzero(FILE *out, int start, int end, char fmt) -{ - bool printed_trailing_newline = false; - bool previously_zero = false; // was previous word printed a 0? - bool printed_dots = false; // have we already printed dots? - int lc = 0; // count of chars on a line - for (int wa = start; wa <= end; wa++) { - if (lc > MAX_PRINT_WIDTH) { - newline(out); - printed_trailing_newline = true; - lc = 0; - } - if (memory.words[wa] != 0) { - lc += print_loc(out, wa, fmt); - printed_trailing_newline = false; - previously_zero = false; - printed_dots = false; - } else { - // memory.words[wa] == 0 - if (!previously_zero) { - // print the first zero - lc += print_loc(out, wa, fmt); - previously_zero = true; - printed_dots = false; - } else { - // previously printed a zero - if (!printed_dots) { - // not already printed the dots, so print them now - lc += fprintf(out, "%s", " ... "); - printed_dots = true; - } - } - printed_trailing_newline = false; - } - } - return printed_trailing_newline; -} - -// print the nonzero memory locations between the word addresses -// start and end (both inclusive) on out, in decimal notation -// a trailing newline was printed if the result is true -static bool print_memory_words_d(FILE *out, int start, int end) -{ - return print_memory_nonzero(out, start, end, 'd'); -} - -// Print the global area, eliding repeated zeros, -// starting at GPR[GP] -static void print_global_data(FILE *out) -{ - int global_wa = GPR[GP]; - bool printed_nl; - printed_nl = print_memory_words_d(out, global_wa, GPR[SP]-1); - if (!printed_nl) { - newline(out); - } -} - -// Requires: a program has been loaded into the computer's memory -// print a heading and the program and any global data -// that were previously loaded into the VM's memory to out -void machine_print_loaded_program(FILE *out) -{ - // heading - instruction_print_table_heading(out); - // instructions - for (int wa = 0; wa < instruction_words; wa++) { - print_instruction(out, wa, memory.instrs[wa]); - } - - print_global_data(out); -} - -// Run the VM on the already loaded program, -// producing any trace output called for by the program -void machine_run(bool trace_execution) -{ - tracing = trace_execution; - if (tracing) { - machine_print_state(stdout); - } - // execute the program - while (running) { - machine_okay(); // check the invariant - machine_trace_execute_instr(stdout, PC, memory.instrs[PC]); - } -} - -// Load the given binary object file and run it -void machine_load_and_run(BOFFILE bf, bool trace_execution) -{ - machine_load(bf); - machine_run(trace_execution); -} - -// Requires: addr == PC. -// If tracing then print the given word address and the assembly form of bi, -// then execute bi (always), -// then if tracing print out the machine's state. -// All tracing output goes to the FILE out -void machine_trace_execute_instr(FILE *out, address_type addr, - bin_instr_t bi) -{ - assert(addr == PC); - if (tracing) { - fprintf(out, "\n==> "); - print_instruction(out, PC, bi); - } - machine_execute_instr(addr, bi); - if (tracing) { - machine_print_state(out); - } -} - -// Requires: The instruction at memory.instrs[PC] is bi. -// Execute the given instruction, which is found at word address addr, -// in the machine's current state -void machine_execute_instr(address_type addr, bin_instr_t bi) -{ - // increment the PC (advance address by 1 word) - PC = PC + 1; - - // execute the actual instruction - instr_type it = instruction_type(bi); - switch (it) { - case comp_instr_type: - { - comp_instr_t ci = bi.comp; - switch (ci.func) { - case NOP_F: - // do nothing - break; - case ADD_F: - memory.words[GPR[ci.rt] + machine_types_formOffset(ci.ot)] - = memory.words[GPR[SP]] - + memory.words[GPR[ci.rs] + machine_types_formOffset(ci.os)]; - break; - case SUB_F: - memory.words[GPR[ci.rt] + machine_types_formOffset(ci.ot)] - = memory.words[GPR[SP]] - - memory.words[GPR[ci.rs] - + machine_types_formOffset(ci.os)]; - break; - case CPW_F: - memory.words[GPR[ci.rt] + machine_types_formOffset(ci.ot)] - = memory.words[GPR[ci.rs] - + machine_types_formOffset(ci.os)]; - break; - case CPR_F: - GPR[ci.rt] = GPR[ci.rs]; - break; - case AND_F: - memory.uwords[GPR[ci.rt] + machine_types_formOffset(ci.ot)] - = memory.uwords[GPR[SP]] - & memory.uwords[GPR[ci.rs] - + machine_types_formOffset(ci.os)]; - break; - case BOR_F: - memory.uwords[GPR[ci.rt] + machine_types_formOffset(ci.ot)] - = memory.uwords[GPR[SP]] - | memory.uwords[GPR[ci.rs] - + machine_types_formOffset(ci.os)]; - break; - case NOR_F: - memory.uwords[GPR[ci.rt] + machine_types_formOffset(ci.ot)] - = ~(memory.uwords[GPR[SP]] - | memory.uwords[GPR[ci.rs] - + machine_types_formOffset(ci.os)]); - break; - case XOR_F: - memory.uwords[GPR[ci.rt] + machine_types_formOffset(ci.ot)] - = memory.uwords[GPR[SP]] - ^ memory.uwords[GPR[ci.rs] - + machine_types_formOffset(ci.os)]; - break; - case LWR_F: - GPR[ci.rt] - = memory.words[GPR[ci.rs] - + machine_types_formOffset(ci.os)]; - break; - case SWR_F: - memory.words[GPR[ci.rt] - + machine_types_formOffset(ci.ot)] - = GPR[ci.rs]; - break; - case SCA_F: - memory.words[GPR[ci.rt] + machine_types_formOffset(ci.ot)] - = (GPR[ci.rs] + machine_types_formOffset(ci.os)); - break; - case LWI_F: - memory.words[GPR[ci.rt] + machine_types_formOffset(ci.ot)] - = memory.words[memory.words - [GPR[ci.rs] + machine_types_formOffset(ci.os)]]; - break; - case NEG_F: - memory.words[GPR[ci.rt] + machine_types_formOffset(ci.ot)] - = - (memory.words[GPR[ci.rs] - + machine_types_formOffset(ci.os)]); - break; - default: - bail_with_error("Invalid function code (%d) in machine_execute's COMP_O computational instruction case!", - ci.func); - break; - } - } - break; - case other_comp_instr_type: - { - other_comp_instr_t oci = bi.othc; - switch (oci.func) { - case LIT_F: - memory.words[GPR[oci.reg] + machine_types_sgnExt(oci.offset)] - = machine_types_sgnExt(oci.arg); - break; - case ARI_F: - GPR[oci.reg] = GPR[oci.reg] + machine_types_sgnExt(oci.arg); - break; - case SRI_F: - GPR[oci.reg] = GPR[oci.reg] - machine_types_sgnExt(oci.arg); - break; - case MUL_F: - hilo_regs.result - = (long) memory.words[GPR[SP]] - * (long) memory.words[GPR[oci.reg] - + machine_types_formOffset(oci.offset)]; - break; - case DIV_F: - int divisor = memory.words[GPR[oci.reg] - + machine_types_formOffset(oci.offset)]; - if (divisor == 0) { - bail_with_error("Error: Attempt to divide by zero!"); - } - hilo_regs.hilo[HI] = memory.words[GPR[SP]] % divisor; - hilo_regs.hilo[LO] = memory.words[GPR[SP]] / divisor; - break; - case CFHI_F: - memory.words[GPR[oci.reg] - + machine_types_formOffset(oci.offset)] - = hilo_regs.hilo[HI]; - break; - case CFLO_F: - memory.words[GPR[oci.reg] - + machine_types_formOffset(oci.offset)] - = hilo_regs.hilo[LO]; - break; - case SLL_F: - memory.uwords[GPR[oci.reg] - + machine_types_formOffset(oci.offset)] - = memory.uwords[GPR[SP]] << oci.arg; - break; - case SRL_F: - memory.uwords[GPR[oci.reg] - + machine_types_formOffset(oci.offset)] - = memory.uwords[GPR[SP]] >> oci.arg; - break; - case JMP_F: - PC = memory.uwords[GPR[oci.reg] - + machine_types_formOffset(oci.offset)]; - break; - case CSI_F: - GPR[RA] = PC; - PC = memory.words[GPR[oci.reg] - + machine_types_formOffset(oci.offset)]; - break; - case JREL_F: - PC = (PC - 1) + machine_types_formOffset(oci.arg); - break; - default: - bail_with_error("Invalid function code (%d) in machine_execute's OTHC_O computational instruction case!", - oci.func); - break; - } - } - break; - case syscall_instr_type: - { - syscall_instr_t si = bi.syscall; - switch (si.code) { - case exit_sc: - running = false; - exit(machine_types_sgnExt(si.offset)); - break; - case print_str_sc: - memory.words[GPR[SP]] - = printf("%s", - (char *) &(memory.words[GPR[si.reg] - + machine_types_formOffset(si.offset)])); - break; - case print_int_sc: - memory.words[GPR[SP]] - = printf("%d", - memory.words[GPR[si.reg] - + machine_types_formOffset(si.offset)]); - break; - case print_char_sc: - memory.words[GPR[SP]] - = fputc(memory.words[GPR[si.reg] - + machine_types_formOffset(si.offset)], - stdout); - break; - case read_char_sc: - memory.words[GPR[si.reg] + machine_types_formOffset(si.offset)] - = getc(stdin); - break; - case start_tracing_sc: - tracing = true; - break; - case stop_tracing_sc: - tracing = false; - break; - default: - bail_with_error("Invalid system call type (%d) in machine_execute's syscall instruction case!", - instruction_syscall_number(bi)); - break; - } - } - break; - case immed_instr_type: - { - immed_instr_t ii = bi.immed; - uimmed_instr_t ui = bi.uimmed; - switch (ii.op) { - case ADDI_O: - memory.words[GPR[ii.reg] + machine_types_formOffset(ii.offset)] - = memory.words[GPR[ii.reg] + machine_types_formOffset(ii.offset)] - + machine_types_sgnExt(ii.immed); - break; - case ANDI_O: - memory.uwords[GPR[ui.reg] + machine_types_formOffset(ui.offset)] - = memory.uwords[GPR[ui.reg] - + machine_types_formOffset(ui.offset)] - & machine_types_zeroExt(ui.uimmed); - break; - case BORI_O: - memory.uwords[GPR[ui.reg] + machine_types_formOffset(ui.offset)] - = memory.uwords[GPR[ui.reg] - + machine_types_formOffset(ui.offset)] - | machine_types_zeroExt(ui.uimmed); - break; - case NORI_O: - memory.uwords[GPR[ui.reg] + machine_types_formOffset(ui.offset)] - = ~(memory.uwords[GPR[ui.reg] - + machine_types_formOffset(ui.offset)] - | machine_types_zeroExt(ui.uimmed)); - break; - case XORI_O: - memory.uwords[GPR[ui.reg] + machine_types_formOffset(ui.offset)] - = memory.uwords[GPR[ui.reg] - + machine_types_formOffset(ui.offset)] - ^ machine_types_zeroExt(ui.uimmed); - break; - case BEQ_O: - if (memory.words[GPR[SP]] - == memory.words[GPR[ii.reg] - + machine_types_formOffset(ii.offset)]) { - PC = (PC - 1) + machine_types_formOffset(ii.immed); - } - break; - case BGEZ_O: - if (memory.words[GPR[ii.reg] - + machine_types_formOffset(ii.offset)] - >= 0) { - PC = (PC - 1) + machine_types_formOffset(ii.immed); - } - break; - case BGTZ_O: - if (memory.words[GPR[ii.reg] - + machine_types_formOffset(ii.offset)] - > 0) { - PC = (PC - 1) + machine_types_formOffset(ii.immed); - } - break; - case BLEZ_O: - if (memory.words[GPR[ii.reg] - + machine_types_formOffset(ii.offset)] - <= 0) { - PC = (PC - 1) + machine_types_formOffset(ii.immed); - } - break; - case BLTZ_O: - if (memory.words[GPR[ii.reg] - + machine_types_formOffset(ii.offset)] - < 0) { - PC = (PC - 1) + machine_types_formOffset(ii.immed); - } - break; - case BNE_O: - if (memory.words[GPR[SP]] - != memory.words[GPR[ii.reg] - + machine_types_formOffset(ii.offset)]) { - PC = (PC - 1) + machine_types_formOffset(ii.immed); - } - break; - default: - bail_with_error("Invalid opcode (%d) in machine_execute's immediate instruction case!", - ii.op); - break; - } - } - break; - case jump_instr_type: - { - jump_instr_t ji = bi.jump; - switch (ji.op) { - case JMPA_O: - PC = machine_types_formAddress(PC-1, ji.addr); - break; - case CALL_O: - GPR[RA] = PC; - PC = machine_types_formAddress(PC-1, ji.addr); - break; - case RTN_O: - PC = GPR[RA]; - break; - default: - bail_with_error("Invalid opcode (%d) in machine_execute's jump instruction case!", - ji.op); - break; - } - } - break; - default: - bail_with_error("Invalid instruction type (%d) in machine_execute!", - it); - break; - } -} - -#define REGFORMAT1 "GPR[%-3s]: %-5d" -#define REGFORMAT2 "\tGPR[%-3s]: %-5d" - -// Requires: out != NULL and is writable -// Print the current values in the registers to out -static void print_registers(FILE *out) -{ - // print the registers - fprintf(out, "%8s: %u", "PC", PC); - if (hilo_regs.result != 0L) { - fprintf(out, "\t%8s: %d\t%8s: %d", - "HI", hilo_regs.hilo[HI], - "LO", hilo_regs.hilo[LO]); - } - newline(out); - - for (int j = 0; j < (NUM_REGISTERS); /* nothing */) { - fprintf(out, REGFORMAT1, regname_get(j), GPR[j]); - j++; - for (int lc = 0; lc < 4 && j < (NUM_REGISTERS); lc++) { - fprintf(out, REGFORMAT2, regname_get(j), GPR[j]); - j++; - } - newline(out); - } -} - -// Print non-zero global data between the (word) addresses -// GPR[SP] and initial_stack_bottom inclusive -static void print_runtime_stack(FILE *out) -{ - // print the memory between sp and fp, inclusive - bool printed_nl = print_memory_words_d(out, GPR[SP], initial_stack_bottom); - if (!printed_nl) { - newline(out); - } -} - -// Requires: out != NULL and out can be written on -// print the state of the machine (registers, globals, and -// the memory between GPR[$sp] and GPR[$fp], inclusive) to out -void machine_print_state(FILE *out) -{ - print_registers(out); - print_global_data(out); - print_runtime_stack(out); -} - -// Invariant test for the VM (for debugging purposes) -// This exits with an assertion error if the invariant does not pass -void machine_okay() -{ - assert(0 <= GPR[GP]); - assert(GPR[GP] < GPR[SP]); - assert(GPR[SP] <= GPR[FP]); - assert(GPR[FP] < MEMORY_SIZE_IN_WORDS); -} diff --git a/vm/machine.h b/vm/machine.h deleted file mode 100755 index 35db2d7..0000000 --- a/vm/machine.h +++ /dev/null @@ -1,50 +0,0 @@ -/* $Id: machine.h,v 1.16 2024/11/10 13:22:31 leavens Exp $ */ -#ifndef _MACHINE_H -#define _MACHINE_H -#include -#include "machine_types.h" -#include "bof.h" -#include "instruction.h" - -// a size for the memory (2^16 = 32K words) -#define MEMORY_SIZE_IN_WORDS 32768 - -// Requires: bf is open for reading in binary -// Load the binary object file bf, and get ready to run it -extern void machine_load(BOFFILE bf); - -// Requires: a program has been loaded into the computer's memory -// print a heading and the program in the VM's memory to out -extern void machine_print_loaded_program(FILE *out); - -// Run the VM on the already loaded program, -// producing any trace output called for by the program -// if trace_execution is true -extern void machine_run(bool trace_execution); - -// Load the given binary object file and run it -extern void machine_load_and_run(BOFFILE bf, bool trace_execution); - -// If tracing then print bi, execute bi (always), -// then if tracing print out the machine's state. -// All tracing output goes to the FILE out -extern void machine_trace_execute_instr(FILE *out, address_type addr, - bin_instr_t bi); - -// Execute the given instruction, which is found at address addr, -// in the machine's current state -extern void machine_execute_instr(address_type addr, bin_instr_t bi); - -// Print instr, execute instr, then print out the machine's state (to out) -extern void machine_trace_execute(FILE *out, bin_instr_t instr); - -// Requires: out != NULL and out can be written on -// print the state of the machine (registers, globals, and -// the memory between GPR[$sp] and GPR[$fp], inclusive) to out -extern void machine_print_state(FILE *out); - -// Invariant test for the VM (for debugging purposes) -// This exits with an assertion error if the invariant does not pass -extern void machine_okay(); - -#endif diff --git a/vm/machine_main.c b/vm/machine_main.c deleted file mode 100755 index 7472c00..0000000 --- a/vm/machine_main.c +++ /dev/null @@ -1,62 +0,0 @@ -/* $Id: machine_main.c,v 1.6 2024/11/10 13:22:31 leavens Exp $ */ -#include -#include -#include -#include "bof.h" -#include "machine.h" -#include "utilities.h" - -/* Print a usage message on stderr and exit with exit code 1. */ -static void usage(const char *cmdname) -{ - bail_with_error( - "Usage: %s [-p] file.bof\n %s [-t] file.bof", - cmdname, cmdname); -} - -// Run the VM on the .bof file name given in argv[1] -int main(int argc, char *argv[]) -{ - const char *cmdname = argv[0]; - argc--; - argv++; - - bool print_program = false; - bool trace_execution = false; - if (argc == 2 && strcmp(argv[0], "-p") == 0) { - print_program = true; - argc--; - argv++; - } else if (argc == 2 && strcmp(argv[0], "-t") == 0) { - trace_execution = true; - argc--; - argv++; - } - - // now there should be exactly 1 file argument - if (argc != 1 || argv[0][0] == '-') { - usage(cmdname); - } - - char *suffix = strchr(argv[0], '.'); - if (suffix == NULL || strncmp(suffix, ".bof", 4) != 0) { - usage(cmdname); - } - - BOFFILE bf = bof_read_open(argv[0]); - - machine_load(bf); - - // if printing, don't run the program - if (print_program) { - machine_print_loaded_program(stdout); - return EXIT_SUCCESS; - } - - machine_run(trace_execution); - - // the following should never execute, - // as the exit system call will call exit(0), - // and if the machine goes into an infinite loop it never gets here! - return EXIT_SUCCESS; -} diff --git a/vm/machine_types.c b/vm/machine_types.c deleted file mode 100755 index e5609db..0000000 --- a/vm/machine_types.c +++ /dev/null @@ -1,100 +0,0 @@ -// $Id: machine_types.c,v 1.12 2024/08/22 11:36:02 leavens Exp $ -#include "machine_types.h" -#include "utilities.h" - -// Return the sign-extended equivalent of i -word_type machine_types_sgnExt(immediate_type i) { - return i; // preserves the value -} - -// Return the zero-extended equivalent of i -uword_type machine_types_zeroExt(immediate_type i) { - return (uword_type) i; -} - -// Return the offset given by o, -// which is the sign extension of o -word_type machine_types_formOffset(immediate_type o) { - return machine_types_sgnExt(o); -} - -// Return an address formed by concatenating the instruction address, a, -// with the high-order (4) bits of the PC. -address_type machine_types_formAddress(address_type PC, address_type a) { - return ((0xF0000000 & PC) | (0x0FFFFFF & a)); -} - -// Check that o can be represented as an offset field in an instruction -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_offset(word_type o) -{ - if (o > NINEBITSMAXSIGNED) { - bail_with_error("Offset is too large: %d", o); - } else if (o < NINEBITSMINSIGNED) { - bail_with_error("Offset is too small: %d", o); - } -} - -// Check that arg can be represented as an arg field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_arg(word_type arg) -{ - if (arg > TWELVEBITSMAXSIGNED) { - bail_with_error("12 bit argument is too large: %d", arg); - } else if (arg < TWELVEBITSMINSIGNED) { - bail_with_error("12 bit argument is too small: %d", arg); - } -} - -// Check that s can be represented as a shift field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_shift(word_type s) -{ - if (s > TWELVEBITSMAXUNSIGNED) { - bail_with_error("Shift is too large: %u", s); - } -} - -// Check that immed can be represented as a signed immediate field, -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_immed(word_type immed) -{ - if (immed > SIXTEENBITSMAXSIGNED) { - bail_with_error("Immediate argument is too large: %d", - immed); - } else if (immed < SIXTEENBITSMINSIGNED) { - bail_with_error("Immediate argument is too small: %d", - immed); - } -} - -// Check that arg can be represented as unsigned immediate field, -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_uimmed(word_type arg) -{ - if (arg > SIXTEENBITSMAXUNSIGNED) { - bail_with_error("Unsigned immediate argument is too large: %u", arg); - } -} - -// Check that addr can be represented as an address field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -void machine_types_check_fits_in_addr(address_type addr) -{ - if (addr > TWENTYEIGHTBITSMAXUNSIGNED) { - bail_with_error("Address is too large: %u", addr); - } -} - -// Return the nearest multiple of BYTES_PER_WORD -// that is greater than or equal to n -int machine_types_round_up_to_wordsize(unsigned int n) -{ - int rem = n % BYTES_PER_WORD; - if (rem == 0) { - return n; - } else { - // assert(((n + (BYTES_PER_WORD - rem)) % BYTES_PER_WORD) == 0); - return n + (BYTES_PER_WORD - rem); - } -} diff --git a/vm/machine_types.h b/vm/machine_types.h deleted file mode 100755 index 6931cab..0000000 --- a/vm/machine_types.h +++ /dev/null @@ -1,94 +0,0 @@ -// $Id: machine_types.h,v 1.29 2024/08/29 21:58:39 leavens Exp $ -// Machine Types for the Simplified Stack Machine (SSM) -#ifndef _MACHINE_TYPES_H -#define _MACHINE_TYPES_H - -#define BYTES_PER_WORD 4 - -// operation codes -typedef unsigned short opcode_type; - -// registers encoded in instructions -typedef unsigned short reg_num_type; - -// offset values (which are signed) encoded in instructions -typedef short offset_type; - -// function codes in computational instructions -typedef unsigned short func_type; - -// argument values (signed) encoded in instructions -typedef short arg_type; - -// shift values encoded in other computational instructions -typedef unsigned short shift_type; - -// immediate operands encoded in instructions -typedef int immediate_type; - -// unsigned immediate operands in instructions -typedef unsigned int uimmed_type; - -// addresses, assuming ints are 32 bits -typedef unsigned int address_type; - -// machine words, assuming ints are 32 bits -typedef int word_type; - -// machine words, unsigned -typedef unsigned int uword_type; - -// bytes, assuming chars are 8 bits -typedef unsigned char byte_type; - -#define NINEBITSMAXSIGNED 0xff -#define NINEBITSMINSIGNED -512 -#define TWELVEBITSMAXSIGNED 0x7ff -#define TWELVEBITSMINSIGNED -0x800 -#define TWELVEBITSMAXUNSIGNED 0xfff -#define SIXTEENBITSMAXSIGNED 0777 -#define SIXTEENBITSMINSIGNED -01000 -#define SIXTEENBITSMAXUNSIGNED 0xffff -#define TWENTYEIGHTBITSMAXUNSIGNED 0xfffffff - -// Return the sign-extended equivalent of i -extern word_type machine_types_sgnExt(immediate_type i); - -// Return the zero-extended equivalent of i -extern uword_type machine_types_zeroExt(immediate_type i); - -// Return the offset given by o, -// which is the sign extension of o -extern word_type machine_types_formOffset(immediate_type o); - -// Return an address formed by concatenating the instruction address, a, -// with the high-order (4) bits of the PC. -extern address_type machine_types_formAddress(address_type PC, address_type a); - -// Check that o can be represented as an offset field in an instruction -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_offset(word_type o); - -// Check that arg can be represented as an arg field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_arg(word_type arg); - -// Check that arg can be represented as a shift field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_shift(word_type arg); - -// Check that immed can be represented as a signed immediate field, -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_immed(word_type immed); - -// Check that arg can be represented as unsigned immediate field, -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_uimmed(word_type arg); - -// Check that addr can be represented as an address field in an instruction, -// bail with an error message if not (so doesn't return if wrong) -extern void machine_types_check_fits_in_addr(address_type addr); - -// the following line is for the documentation -// ... -#endif diff --git a/vm/parser_test0.asm b/vm/parser_test0.asm deleted file mode 100755 index 4c3bf05..0000000 --- a/vm/parser_test0.asm +++ /dev/null @@ -1,6 +0,0 @@ - # $Id: parser_test0.asm,v 1.3 2024/07/30 12:00:15 leavens Exp $ -.text start -start: EXIT 0 -.data 16 -.stack 4096 -.end diff --git a/vm/parser_test0.lst b/vm/parser_test0.lst deleted file mode 100755 index dcf57f6..0000000 --- a/vm/parser_test0.lst +++ /dev/null @@ -1,3 +0,0 @@ -Address Instruction - 0: EXIT 0 - 16: 0 ... diff --git a/vm/parser_test1.asm b/vm/parser_test1.asm deleted file mode 100755 index ad34249..0000000 --- a/vm/parser_test1.asm +++ /dev/null @@ -1,12 +0,0 @@ - # $Id: parser_test1.asm,v 1.5 2024/07/30 12:00:15 leavens Exp $ - -.text begin -begin: SUB $sp, 0, $sp, 0 - EXIT 0 -.data 0x40 - WORD b = 10 - WORD w - WORD c - WORD sixteen = 16 -.stack 0x4040 -.end diff --git a/vm/parser_test1.lst b/vm/parser_test1.lst deleted file mode 100755 index be56d75..0000000 --- a/vm/parser_test1.lst +++ /dev/null @@ -1,5 +0,0 @@ -Address Instruction - 0: SUB $sp, 0, $sp, 0 - 1: EXIT 0 - 64: 10 65: 0 ... 67: 16 68: 0 - ... diff --git a/vm/parser_test2.asm b/vm/parser_test2.asm deleted file mode 100755 index 90da209..0000000 --- a/vm/parser_test2.asm +++ /dev/null @@ -1,14 +0,0 @@ - # $Id: parser_test2.asm,v 1.4 2024/08/20 00:05:26 leavens Exp $ - .text start -start: NOP - ADDI $sp, 0, 1 - SCA $sp, -1, $sp, 0 - SRI $sp, 1 - SWR $sp, -1, $fp - ADDI $sp, -1, 104 - LWI $sp, -2, $gp, 0 - EXIT 0 - .data 104 - WORD fourtytwo = 42 - .stack 4200 - .end diff --git a/vm/parser_test2.lst b/vm/parser_test2.lst deleted file mode 100755 index 42a6e69..0000000 --- a/vm/parser_test2.lst +++ /dev/null @@ -1,10 +0,0 @@ -Address Instruction - 0: NOP - 1: ADDI $sp, 0, 1 - 2: SCA $sp, -1, $sp, 0 - 3: SRI $sp, 1 - 4: SWR $sp, -1, $fp - 5: ADDI $sp, -1, 104 - 6: LWI $sp, -2, $gp, 0 - 7: EXIT 0 - 104: 42 105: 0 ... diff --git a/vm/parser_test3.asm b/vm/parser_test3.asm deleted file mode 100755 index a626e73..0000000 --- a/vm/parser_test3.asm +++ /dev/null @@ -1,13 +0,0 @@ - # $Id: parser_test3.asm,v 1.5 2024/07/30 12:00:15 leavens Exp $ - .text start -start: ARI $sp, -2 - BNE $sp, 1, +4 - ADDI $sp, 0, 100 - ADD $sp, 0, $gp, 0 - EXIT 0 - .data 1024 - WORD hundred = 100 - WORD forty = 40 - WORD six = 6 - .stack 4096 - .end diff --git a/vm/parser_test3.lst b/vm/parser_test3.lst deleted file mode 100755 index 7be8ad7..0000000 --- a/vm/parser_test3.lst +++ /dev/null @@ -1,8 +0,0 @@ -Address Instruction - 0: ARI $sp, -2 - 1: BNE $sp, 1, 4 # target is word address 5 - 2: ADDI $sp, 0, 100 - 3: ADD $sp, 0, $gp, 0 - 4: EXIT 0 - 1024: 100 1025: 40 1026: 6 1027: 0 ... - diff --git a/vm/parser_test4.asm b/vm/parser_test4.asm deleted file mode 100755 index f7b37b5..0000000 --- a/vm/parser_test4.asm +++ /dev/null @@ -1,10 +0,0 @@ - # $Id: parser_test4.asm,v 1.5 2024/07/30 12:00:15 leavens Exp $ - .text start -start: ARI $sp, -2 - BNE $sp, -1, +1 # shouldn't be effective, as both what $sp and $sp-1 - # point to should contain 0 - EXIT 0 - .data 2048 - WORD five = +5 - .stack 6144 - .end diff --git a/vm/parser_test4.lst b/vm/parser_test4.lst deleted file mode 100755 index 7fbe86b..0000000 --- a/vm/parser_test4.lst +++ /dev/null @@ -1,5 +0,0 @@ -Address Instruction - 0: ARI $sp, -2 - 1: BNE $sp, -1, 1 # target is word address 2 - 2: EXIT 0 - 2048: 5 2049: 0 ... diff --git a/vm/parser_test5.asm b/vm/parser_test5.asm deleted file mode 100755 index 34a64be..0000000 --- a/vm/parser_test5.asm +++ /dev/null @@ -1,58 +0,0 @@ - # $Id: parser_test5.asm,v 1.13 2024/08/29 02:05:03 leavens Exp $ - -.text here - -here: LIT $sp, 0, 0 - SUB $sp, -1, $sp, 0 - AND $sp, -2, $sp, -3 - SRI $sp, 3 - BORI $sp, 0, 0x8 - JREL 3 # skip next 2 instructions - NOR $ra, -1, $sp, 0 # causes an error - XOR $sp, -2, $sp, -1 # why not? - MUL $r5, 0 - CFHI $1, 0 - CFLO $2, 0 - LIT $sp, -1, 1 - LWR $r5, $sp, -1 # put 1 in $r5 - SRI $sp, 1 - DIV $sp, 0 - ADDI $sp, 0, 13 - ADD $gp, 0, $gp, 0 - CALL fun - EXIT 0 -fun: ANDI $sp, 0, 0xff - XORI $sp, 0, 0x00 - BEQ $sp, 0, 2 - BNE $sp, 0, 333 - BGEZ $sp, 0, 3 - ADDI $sp, 0, 11 - BGTZ $sp, 1, -2 - BLTZ $sp, 1, 2 - BLEZ $sp, 0, 2 - CPW $sp, 0, $gp, 1 # put 1025 in stack top - LWR $fp, $sp, 0 # put 1025 in $fp register, violates invariant! - ARI $sp, -1 # allocate a word on the stack - CPW $sp, 0, $gp, 1 # put 1025 in stack top - ADDI $sp, 0, -1 # make $sp be 1024 - SUB $sp, 0, $sp, 0 # zero out the top of the stack - ARI $sp, -1 # allocate a word on the stack - CPW $gp, 2, $sp, 0 # put 'Y' on top of stack - SLL $sp, 0, 8 # shift it 8 bits to the left - BOR $sp, 0, $gp, 0 # put '\n' on top of stack - PCH $sp, 1 # print the 'Y' - PCH $sp, 0 # print '\n' - RTN - SUB $sp, 0, $sp, 0 # zero out the top of the stack - DIV $sp, 0 # cause a division by 0 error - EXIT 1 - -.data 2048 - CHAR nl = '\n' - WORD newsp = 1025 - CHAR ychar = 'Y' - WORD c - WORD sixteen = 0x10 - -.stack 6144 -.end diff --git a/vm/parser_test5.lst b/vm/parser_test5.lst deleted file mode 100755 index 72103e3..0000000 --- a/vm/parser_test5.lst +++ /dev/null @@ -1,47 +0,0 @@ -Address Instruction - 0: LIT $sp, 0, 0 - 1: SUB $sp, -1, $sp, 0 - 2: AND $sp, -2, $sp, -3 - 3: SRI $sp, 3 - 4: BORI $sp, 0, 0x8 - 5: JREL 3 # target is word address 8 - 6: NOR $ra, -1, $sp, 0 - 7: XOR $sp, -2, $sp, -1 - 8: MUL $r5, 0 - 9: CFHI $sp, 0 - 10: CFLO $fp, 0 - 11: LIT $sp, -1, 1 - 12: LWR $r5, $sp, -1 - 13: SRI $sp, 1 - 14: DIV $sp, 0 - 15: ADDI $sp, 0, 13 - 16: ADD $gp, 0, $gp, 0 - 17: CALL 19 # target is word address 19 - 18: EXIT 0 - 19: ANDI $sp, 0, 0xff - 20: XORI $sp, 0, 0x0 - 21: BEQ $sp, 0, 2 # target is word address 23 - 22: BNE $sp, 0, 333 # target is word address 355 - 23: BGEZ $sp, 0, 3 # target is word address 26 - 24: ADDI $sp, 0, 11 - 25: BGTZ $sp, 1, -2 # target is word address 23 - 26: BLTZ $sp, 1, 2 # target is word address 28 - 27: BLEZ $sp, 0, 2 # target is word address 29 - 28: CPW $sp, 0, $gp, 1 - 29: LWR $fp, $sp, 0 - 30: ARI $sp, -1 - 31: CPW $sp, 0, $gp, 1 - 32: ADDI $sp, 0, -1 - 33: SUB $sp, 0, $sp, 0 - 34: ARI $sp, -1 - 35: CPW $gp, 2, $sp, 0 - 36: SLL $sp, 0, 8 - 37: BOR $sp, 0, $gp, 0 - 38: PCH $sp, 1 - 39: PCH $sp, 0 - 40: RTN - 41: SUB $sp, 0, $sp, 0 - 42: DIV $sp, 0 - 43: EXIT 1 - 2048: 10 2049: 1025 2050: 89 2051: 0 2052: 16 - 2053: 0 ... diff --git a/vm/parser_test6.asm b/vm/parser_test6.asm deleted file mode 100755 index f3db38e..0000000 --- a/vm/parser_test6.asm +++ /dev/null @@ -1,36 +0,0 @@ -# $Id: parser_test6.asm,v 1.5 2024/08/28 21:25:00 leavens Exp $ -.text start -zero: SUB $sp, 0, $sp, 0 - AND $sp, 0, $sp, 0 - BOR $sp, 0, $sp, 0 - NOR $sp, 0, $sp, 0 # why? - XOR $sp, 0, $sp, 0 # & why not? - MUL $sp, 0 - CFHI $sp, 0 - CFLO $sp, -1 - RTN -start: ADDI $sp, 0, 13 - ADD $sp, 0, $ra, 0 - CALL zero - ANDI $sp, 0, 0x8 - XORI $sp, -1, 0x567a - BEQ $sp, -1, 2 - BNE $sp, -1, 4 - BGEZ $sp, 0, 3 - BGTZ $sp, 0, 2 - BLTZ $sp, 0, 1 - BLEZ $sp, 1, 2 - SRI $sp, 1 - LIT $sp, 0, 100 - LIT $sp, -1, 10 - MUL $sp, -1 - STRA - NOTR - EXIT 0 -.data 2048 -WORD w0 = 10 -WORD w1 = 0 -WORD w2 = -52345 -WORD w3 = 16 -.stack 6144 -.end diff --git a/vm/parser_test6.lst b/vm/parser_test6.lst deleted file mode 100755 index 1bb1a9b..0000000 --- a/vm/parser_test6.lst +++ /dev/null @@ -1,30 +0,0 @@ -Address Instruction - 0: SUB $sp, 0, $sp, 0 - 1: AND $sp, 0, $sp, 0 - 2: BOR $sp, 0, $sp, 0 - 3: NOR $sp, 0, $sp, 0 - 4: XOR $sp, 0, $sp, 0 - 5: MUL $sp, 0 - 6: CFHI $sp, 0 - 7: CFLO $sp, -1 - 8: RTN - 9: ADDI $sp, 0, 13 - 10: ADD $sp, 0, $ra, 0 - 11: CALL 0 # target is word address 0 - 12: ANDI $sp, 0, 0x8 - 13: XORI $sp, -1, 0x567a - 14: BEQ $sp, -1, 2 # target is word address 16 - 15: BNE $sp, -1, 4 # target is word address 19 - 16: BGEZ $sp, 0, 3 # target is word address 19 - 17: BGTZ $sp, 0, 2 # target is word address 19 - 18: BLTZ $sp, 0, 1 # target is word address 19 - 19: BLEZ $sp, 1, 2 # target is word address 21 - 20: SRI $sp, 1 - 21: LIT $sp, 0, 100 - 22: LIT $sp, -1, 10 - 23: MUL $sp, -1 - 24: STRA - 25: NOTR - 26: EXIT 0 - 2048: 10 2049: 0 2050: -52345 2051: 16 2052: 0 - ... diff --git a/vm/parser_types.h b/vm/parser_types.h deleted file mode 100755 index 05192cb..0000000 --- a/vm/parser_types.h +++ /dev/null @@ -1,11 +0,0 @@ -/* $Id: parser_types.h,v 1.5 2023/09/09 20:45:49 leavens Exp $ */ -#ifndef _PARSER_TYPES_H -#define _PARSER_TYPES_H - -#include "ast.h" - -// The type of Bison's parser stack elements (parse values) -typedef AST YYSTYPE; -#define YYSTYPE_IS_DECLARED 1 - -#endif diff --git a/vm/pass1.c b/vm/pass1.c deleted file mode 100755 index 8ca306c..0000000 --- a/vm/pass1.c +++ /dev/null @@ -1,143 +0,0 @@ -// $Id: pass1.c,v 1.6 2024/07/29 02:01:32 leavens Exp $ -#include -#include "pass1.h" -#include "symtab.h" -#include "utilities.h" - -// Build the symbol table and check for duplicate declarations in the given AST -void pass1(ast_program_t progast) -{ - symtab_initialize(); - pass1TextSection(progast.textSection); - pass1DataSection(progast.dataSection); -} - -// Check the given AST and put its declarations in the symbol table -void pass1TextSection(ast_text_section_t ts) -{ - pass1AsmInstrs(ts.instrs); -} - -// Check the given AST and put its declarations in the symbol table -void pass1AsmInstrs(ast_asm_instrs_t instrs) -{ - ast_asm_instr_t *ip = instrs.instrs; - address_type count = 0; - while (ip != NULL) { - pass1AsmInstr(*ip, count); - ip = ip->next; - count++; - } -} - -// Check the given AST and put its declarations in the symbol table -void pass1AsmInstr(ast_asm_instr_t instr, address_type count) -{ - pass1LabelOpt(instr.label_opt, count); -} - -// Check the given AST and put its declarations in the symbol table -void pass1LabelOpt(ast_label_opt_t lopt, address_type count) -{ - if (lopt.name != NULL) { - id_attrs_assoc attrs; - if (symtab_defined(lopt.name)) { - bail_with_error("Duplicate declaration of label \"%s\"", - lopt.name); - } - attrs.name = lopt.name; - attrs.kind = id_label; - attrs.addr = count; - symtab_insert(attrs); - } -} - -// Check the given AST and put its declarations in the symbol table -void pass1DataSection(ast_data_section_t ds) -{ - pass1StaticDecls(ds.staticDecls); -} - -// Check the given AST and put its declarations in the symbol table -void pass1StaticDecls(ast_static_decls_t sds) -{ - address_type offset = 0; - ast_static_decl_t *dcl = sds.decls; - while (dcl != NULL) { - pass1StaticDecl(*dcl, offset); - offset += dcl->size_in_words; - dcl = dcl->next; - } -} - -// Check the given AST and put its declarations in the symbol table -void pass1StaticDecl(ast_static_decl_t dcl, address_type offset) -{ - pass1DeclareIdent(dcl.ident, offset); -} - -// Check the given AST and put its declarations in the symbol table -void pass1DeclareIdent(ast_ident_t id, address_type offset) -{ - if (symtab_defined(id.name)) { - bail_with_error("Duplicate declaration of data name \"%s\"", - id.name); - } - id_attrs_assoc assoc; - assoc.name = id.name; - assoc.kind = id_data; - assoc.addr = offset; - symtab_insert(assoc); -} - -// Print, on out, the header line for the printed output -// followed by a newline -static void pass1_print_header(FILE *out) -{ - fprintf(out, "%-5s %s\t%s\n", "Kind", "Name", "Address"); -} - -static const char *id_attr_kind_2_string(id_attr_kind k) { - switch (k) { - case id_label: - return "Label"; - break; - case id_data: - return "Data"; - break; - default: - bail_with_error("Unknown id_attr_kind in id_attr_kind_2_string (%d)", - k); - break; - } - return NULL; -} - -// Requires: symtab_defined(name); -// Print, on out, a line with the symbol table's information about name -// followed by a newline -static void pass1_print_name_info(FILE *out, const char *name) -{ - id_attrs_assoc na, *assoc; - assoc = symtab_lookup(name); - if (assoc == NULL) { - bail_with_error("pass1_print_name_info given NULL pointer!"); - } else { - na = *assoc; - } - fprintf(out, "%-5s %s\t%u\n", id_attr_kind_2_string(na.kind), - na.name, na.addr); -} - -// Requires: out is a character file (like stdout) -// that is open for writing -// Print debugging information about the symbol table on out -void pass1_print(FILE *out) -{ - pass1_print_header(out); - const char *name = name = symtab_first_name(); - while (symtab_more_after(name)) { - pass1_print_name_info(out, name); - name = symtab_next_name(name); - } -} diff --git a/vm/pass1.h b/vm/pass1.h deleted file mode 100755 index 85e283c..0000000 --- a/vm/pass1.h +++ /dev/null @@ -1,40 +0,0 @@ -// $Id: pass1.h,v 1.4 2024/07/26 12:44:46 leavens Exp $ -#ifndef _PASS1_H -#define _PASS1_H -#include -#include "ast.h" -#include "machine_types.h" - -// Build the symbol table and check for duplicate declarations in the given AST -extern void pass1(ast_program_t progast); - -// Check the given AST and put its declarations in the symbol table -extern void pass1TextSection(ast_text_section_t ts); - -// Check the given AST and put its declarations in the symbol table -extern void pass1AsmInstrs(ast_asm_instrs_t instrs); - -// Check the given AST and put its declarations in the symbol table -extern void pass1AsmInstr(ast_asm_instr_t instr, address_type count); - -// Check the given AST and put its declarations in the symbol table -extern void pass1LabelOpt(ast_label_opt_t lopt, address_type count); - -// Check the given AST and put its declarations in the symbol table -extern void pass1DataSection(ast_data_section_t ds); - -// Check the given AST and put its declarations in the symbol table -extern void pass1StaticDecls(ast_static_decls_t sds); - -// Check the given AST and put its declarations in the symbol table -extern void pass1StaticDecl(ast_static_decl_t dcl, address_type offset); - -// Check the given AST and put its declarations in the symbol table -extern void pass1DeclareIdent(ast_ident_t id, address_type offset); - -// Requires: out is a character file (like stdout) -// that is open for writing -// Print debugging information about the symbol table on out -void pass1_print(FILE *out); - -#endif diff --git a/vm/regname.c b/vm/regname.c deleted file mode 100755 index 158869b..0000000 --- a/vm/regname.c +++ /dev/null @@ -1,12 +0,0 @@ -// $Id: regname.c,v 1.3 2024/07/29 12:38:50 leavens Exp $ -#include "regname.h" - -static const char *regnames[NUM_REGISTERS] = { - "$gp", "$sp", "$fp", "$r3", "$r4", "$r5", "$r6", "$ra" }; - -// requires 0 <= n && n < NUM_REGISTERS -// Return the standard symbolic name for n -const char *regname_get(reg_num_type n) -{ - return regnames[n]; -} diff --git a/vm/regname.h b/vm/regname.h deleted file mode 100755 index 33208df..0000000 --- a/vm/regname.h +++ /dev/null @@ -1,18 +0,0 @@ -// $Id: regname.h,v 1.5 2024/07/29 12:38:50 leavens Exp $ -#ifndef _REGNAME_H -#define _REGNAME_H -#include "machine_types.h" - -#define NUM_REGISTERS 8 - -// some important register numbers in the ISA -#define GP 0 -#define SP 1 -#define FP 2 -#define RA 7 - -// requires 0 <= n && n < NUM_REGISTERS -// Return the standard symbolic name for n -extern const char *regname_get(reg_num_type n); -#endif - diff --git a/vm/run-tests.sh b/vm/run-tests.sh deleted file mode 100755 index 3066907..0000000 --- a/vm/run-tests.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -: ${PREFIX=lexer_test} -for suf in bof lst out -do - for i in $@ - do - rm -f ${PREFIX}${i}.${suf} - make IMTHEINSTRUCTOR=true ${PREFIX}${i}.${suf} - done -done diff --git a/vm/show_magic.c b/vm/show_magic.c deleted file mode 100755 index b048fd7..0000000 --- a/vm/show_magic.c +++ /dev/null @@ -1,12 +0,0 @@ -// $Id: show_magic.c,v 1.1 2024/07/09 17:48:37 leavens Exp $ - -#include -#include -#include "bof.h" - -extern void bof_write_magic(FILE *f); - -int main() { - bof_write_magic(stdout); - exit(EXIT_SUCCESS); -} diff --git a/vm/srm-asm.aux b/vm/srm-asm.aux deleted file mode 100755 index 4cadcd4..0000000 --- a/vm/srm-asm.aux +++ /dev/null @@ -1,36 +0,0 @@ -\relax -\providecommand\hyper@newdestlabel[2]{} -\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument} -\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined -\global\let\oldnewlabel\newlabel -\gdef\newlabel#1#2{\newlabelxx{#1}#2} -\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} -\AtEndDocument{\ifx\hyper@anchor\@undefined -\let\newlabel\oldnewlabel -\fi} -\fi} -\global\let\hyper@last\relax -\gdef\HyperFirstAtBeginDocument#1{#1} -\providecommand\HyField@AuxAddToFields[1]{} -\providecommand\HyField@AuxAddToCoFields[2]{} -\bibstyle{plain} -\citation{Kane-Heinrich92} -\@writefile{toc}{\contentsline {section}{\numberline {1}Overview}{1}{section.1}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {1.1}Inputs and Outputs}{1}{subsection.1.1}\protected@file@percent } -\@writefile{toc}{\contentsline {subsubsection}{\numberline {1.1.1}Assembler}{1}{subsubsection.1.1.1}\protected@file@percent } -\@writefile{toc}{\contentsline {subsubsection}{\numberline {1.1.2}Disassembler}{1}{subsubsection.1.1.2}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {1.2}Error Outputs}{2}{subsection.1.2}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {1.3}Exit Code}{2}{subsection.1.3}\protected@file@percent } -\@writefile{toc}{\contentsline {section}{\numberline {2}Assembly Language Syntax}{2}{section.2}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Lexical Grammar}{2}{subsection.2.1}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Context-Free Grammar}{2}{subsection.2.2}\protected@file@percent } -\@writefile{toc}{\contentsline {section}{\numberline {3}Initial Values}{2}{section.3}\protected@file@percent } -\newlabel{sec:initialvalues}{{3}{2}{Initial Values}{section.3}{}} -\@writefile{toc}{\contentsline {section}{\numberline {4}Constraints on Assembly Code}{2}{section.4}\protected@file@percent } -\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Lexical grammar of the SRM assembler. This grammar uses a \texttt {terminal font} for terminal symbols. Note that an underbar (\texttt {\_}) and all ASCII letters (a-z and A-Z) are included in the production for \mbox {$\langle $\textrm {letter}$\rangle $}. Curly brackets, such as $\{x\}$, mean an arbitrary number of (i.e., 0 or more) repetitions of $x$. Note that curly braces are not terminal symbols in this grammar. Some character classes are described in English, these are described in a Roman font between double quotation marks (`` and ''). Note that all characters matched by the nonterminal \mbox {$\langle $\textrm {ignored}$\rangle $} are ignored by the lexer. However, the characters that are part of an \mbox {$\langle $\textrm {eol}$\rangle $} token (i.e., carriage returns and newlines) are not ignored immediately following a semicolon, \mbox {$\langle $\textrm {reserved-opcode}$\rangle $} or \mbox {$\langle $\textrm {reserved-data-size}$\rangle $}, although they are ignored in all other contexts. }}{3}{figure.1}\protected@file@percent } -\newlabel{fig:lexical-grammar}{{1}{3}{Lexical grammar of the SRM assembler. This grammar uses a \texttt {terminal font} for terminal symbols. Note that an underbar (\texttt {\_}) and all ASCII letters (a-z and A-Z) are included in the production for \nonterm {letter}. Curly brackets, such as $\arbno {x}$, mean an arbitrary number of (i.e., 0 or more) repetitions of $x$. Note that curly braces are not terminal symbols in this grammar. Some character classes are described in English, these are described in a Roman font between double quotation marks (`` and ''). Note that all characters matched by the nonterminal \nonterm {ignored} are ignored by the lexer. However, the characters that are part of an \nonterm {eol} token (i.e., carriage returns and newlines) are not ignored immediately following a semicolon, \nonterm {reserved-opcode} or \nonterm {reserved-data-size}, although they are ignored in all other contexts}{figure.1}{}} -\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces The (context free) grammar of the SRM assembler, which uses a \texttt {typewriter font} for terminal symbols. }}{4}{figure.2}\protected@file@percent } -\newlabel{fig:cfg}{{2}{4}{The (context free) grammar of the SRM assembler, which uses a \texttt {typewriter font} for terminal symbols}{figure.2}{}} -\bibdata{srm-vm.bib} -\bibcite{Kane-Heinrich92}{1} -\gdef \@abspage@last{5} diff --git a/vm/srm-asm.bbl b/vm/srm-asm.bbl deleted file mode 100755 index 125f80e..0000000 --- a/vm/srm-asm.bbl +++ /dev/null @@ -1,8 +0,0 @@ -\begin{thebibliography}{1} - -\bibitem{Kane-Heinrich92} -Gerry Kane and Joe Heinrich. -\newblock {\em {MIPS RISC} architectures}. -\newblock Prentice-Hall, Inc., 1992. - -\end{thebibliography} diff --git a/vm/srm-asm.tex b/vm/srm-asm.tex deleted file mode 100755 index 9b71985..0000000 --- a/vm/srm-asm.tex +++ /dev/null @@ -1,322 +0,0 @@ -% $Id: srm-asm.tex,v 1.29 2023/09/20 19:43:09 leavens Exp $ -\documentclass[11pt,letterpaper]{article} -\usepackage[T1]{fontenc} -\usepackage{times} -\usepackage{textcomp} %required to set upquote flag and for luximono -%\usepackage[scaled=0.81]{luximono} -\usepackage{enumitem} -\usepackage{listings} -\usepackage{color} -\usepackage{ragged2e} -\lstset{language=C,basicstyle=\ttfamily,commentstyle=\rmfamily\itshape} -\lstset{morecomment=[l]{//}, %use comment-line-style! - morecomment=[s]{/*}{*/}} %for multiline comments -\lstset{upquote=true} %FH -% The following is needed for C programs -\lstset{showspaces=false,showstringspaces=false} -%\lstset{mathescape=true} -\input{boxed-figure-new} -% getting files for figures -\newcommand{\LSTFILE}[1]{ -\lstinputlisting[basicstyle=\small\ttfamily]{#1} -} -\newcommand{\LSTFILESLICE}[2]{ -\lstinputlisting[basicstyle=\small\ttfamily,linerange={#1}]{#2} -} -% -\newcommand{\LSTCFILE}[1]{ -\lstinputlisting[language=C,basicstyle=\small\ttfamily]{#1} -} -\usepackage[bookmarks=false]{hyperref} -%\usepackage{varioref} % doesn't work with hyperref, it seems, sigh -%\renewcommand{\reftextfacebefore}{on the previous page} -%\renewcommand{\reftextfaceafter}{on the next page} -\newcommand{\tabref}[1]{Table~\ref{#1}} % vref from varioref -\newcommand{\tabnref}[1]{Table~\ref{#1}} % doesn't use varioref -\newcommand{\figref}[1]{Figure~\ref{#1}} % vref from varioref -\newcommand{\fignref}[1]{Figure~\ref{#1}} % doesn't use varioref -\newcommand{\secref}[1]{Section~\ref{#1}} % vref from varioref -\newcommand{\secnref}[1]{Section~\ref{#1}} % doesn't use varioref - -\input{obey} -\input{grammar} -\renewcommand{\nonterm}[1]{\mbox{$\langle$\textrm{#1}$\rangle$}} -\renewcommand{\arbno}[1]{\{#1\}} -\newcommand{\gramquote}[1]{\textrm{`}#1\textrm{'}} -\input{use-full-height} -\input{use-full-width} -\input{continuedenum} - -\setlength\RaggedRightParindent{\parindent} -\input{srm-isa.tex} -\newcommand{\IFO}[2]{\textrm{\textbf{if} \ensuremath{#1} \textbf{then} \ensuremath{#2} }} -\newcommand{\IF}[3]{\textrm{\textbf{if} #1 \textbf{then} #2 \textbf{else} #3}} -\newcommand{\EQUALS}{\ensuremath{=}} % or {\ensuremath{\:\texttt{==}\:}} -% -\bibliographystyle{plain} -% -\title{Simplified RISC Machine Assembler Manual \\ - (\lstinline!$Revision: 1.29 $!)} -\author{Gary T. Leavens \\ - Leavens@ucf.edu} -\begin{document} - -\maketitle -\begin{abstract} -This document defines the assembly language for the -Simplified RISC Machine VM, which is used in the Systems Software -class (COP 3402) at UCF. -It also defines the interface of the assembler and disassembler. -\end{abstract} - -\section{Overview} - -The assembler for the Simplified RISC Machine (SRM) is simple and has -no macro facilities. However, it does let one assemble the -instructions that make up a program, resolving symbolic names for jump targets, -and it can define the starting -address of a program and the program's (static) data section. -The opcodes generally follow those for the MIPS processor's ISA -\cite{Kane-Heinrich92} albeit in simplified form. - -The assembler assumes that the SRM has $\WS$-bit ($\WSinBytes$-byte) -words and is byte-addressable. - -\subsection{Inputs and Outputs} - -\subsubsection{Assembler} - -The assembler is passed a single file name as its only command line argument; -this file should be the name of a (readable) assembler program; -its output (sent to standard output) is a binary object file. - -For example, if the program is contained in the file -\texttt{myProg.srm}, assuming that the assembler is named \texttt{asm}, -(and both these files are in the current directory), then the assembler -can be invoked as follows in the Unix shell to produce a binary object file on standard output. -\begin{lstlisting} - ./asm myProg.srm -\end{lstlisting} - -Thus, to put the assembled version of \texttt{myProg.srm} into the file \texttt{myProg.bof}, -one would use a Unix command that redirects the output of the assembler into \texttt{myProg.bof}, as follows. - -\begin{lstlisting} - ./asm myProg.srm > myProg.bof -\end{lstlisting} - -\subsubsection{Disassembler} - -The disassembler is the opposite of the assembler. -It is passed a single file name, but that file names a (readable) binary object -file, and it produces, on standard output, -an assembly language source program. - -For example, if the binary object file is found in \texttt{prog.bof}, -assuming that the disassembler is named \texttt{disasm}, -(and both these files are in the current directory), then the disassembler -can be invoked as follows in the Unix shell to produce (on standard -output) an assembly language program that would compile to \texttt{prog.bof}. - -\begin{lstlisting} - ./disasm prog.bof -\end{lstlisting} - -The assembly language program can be redirected into the file \texttt{prog.srm} as follows. - -\begin{lstlisting} - ./disasm prog.bof > prog.srm -\end{lstlisting} - -\subsection{Error Outputs} - -All error messages (e.g., for file permission errors or syntax errors) -are sent to standard error output (\texttt{stderr}). - -\subsection{Exit Code} - -When the either program halts normally, it exits with a zero error code -(which indicates success on Unix). However, when \texttt{asm} or -\texttt{disasm} encounters an error, -it halts and exits with a non-zero exit code -(which indicates failure on Unix). - -\section{Assembly Language Syntax} - -\subsection{Lexical Grammar} - -Tokens in the assembler are described by the (regular) -grammar of \figref{fig:lexical-grammar}. -Note that line endings are significant in the context-free grammar of -the assembler, as each instruction must be specified on a single line. -Lines may be ended either by a newline character (\nonterm{newline} in -\figref{fig:lexical-grammar}) -or by a combination of a carriage-return (\nonterm{cr}) followed by a newline. -Comments (\nonterm{comment}) start with a \nonterm{comment-start} (i.e., \texttt{\#}) -and continue to the end of a line. -White space is needed to separate tokens, but is otherwise ignored. - -\begin{figure} -\begin{grammar} -\nonterm{section-mark} \: .text \| .data \| .end -\nonterm{reserved-opcode} \: ADD \| SUB \| AND \| BOR \| NOR \| XOR \| MUL \| DIV -\> \| \> SLL \| SRL \| MFHI \| MFLO \| JR \| ADDI \| ANDI \| BORI \| XORI \| BEQ -\> \| \> BGEZ \| BGTZ \| BLTZ \| LBU \| LW \| SB \| SW \| JMP \| JAL -\nonterm{reserved-data-size} \: WORD -\nonterm{ident} \: \nonterm{letter} \arbno{\nonterm{letter-or-digit}} \textrm{``but not a \nonterm{reserved-opcode} or \nonterm{reserved-data-size}''} -\nonterm{letter} \: \_ \| a \| b \| $\ldots$ \| y \| z \| A \| B \| $\ldots$ \| Y \| Z -\nonterm{letter-or-digit} \: \nonterm{letter} \| \nonterm{dec-digit} - -\nonterm{unsigned-number} \: \nonterm{dec-digit} \arbno{\nonterm{dec-digit}} - \> \| \> 0x \nonterm{hex-digit} \arbno{\nonterm{hex-digit}} -\nonterm{dec-digit} \: 0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 -\nonterm{hex-digit} \: \nonterm{dec-digit} \| a \| A \| b \| B \| c \| C \| d \| D \| e \| E \| f \| F - -\nonterm{reg} \: \nonterm{dollar-sign} \nonterm{unsigned-number} \| \$at \| \$v0 \| \$v1 -\> \| \> \$a0 \| \$a1 \| \$a2 \| \$a3 \| \$t0 \| \$t1 \| \$t2 \| \$t3 \| \$t4 \| \$t5 \| \$t6 \| \$t7 -\> \| \> \$s0 \| \$s1 \| \$s2 \| \$s3 \| \$s4 \| \$s5 \| \$s6 \| \$s7 \| \$t8 \| \$t9 -\> \| \> \$gp \| \$sp \| \$fp \| \$ra -\nonterm{dollar-sign} \: \$ - -\nonterm{eol} \: \nonterm{newline} \| \nonterm{cr} \nonterm{newline} -\nonterm{newline} \: \textrm{``A newline character (ASCII 10)''} -\nonterm{cr} \: \textrm{``A carriage return character (ASCII 13)''} - -\nonterm{ignored} \: \nonterm{blank} \| \nonterm{tab} \| \nonterm{vt} \| \nonterm{formfeed} \| \nonterm{comment} -\nonterm{blank} \: \textrm{``A space character (ASCII 32)''} -\nonterm{tab} \: \textrm{``A horizontal tab character (ASCII 9)''} -\nonterm{vt} \: \textrm{``A vertical tab character (ASCII 11)''} -\nonterm{formfeed} \: \textrm{``A formfeed character (ASCII 12)''} -\nonterm{comment} \: \nonterm{comment-start} \arbno{\nonterm{non-nl}} -\nonterm{comment-start} \: \# -\nonterm{non-nl} \: \textrm{``Any character except a newline''} -\end{grammar} -\caption{ - Lexical grammar of the SRM assembler. - This grammar uses a \texttt{terminal font} - for terminal symbols. Note that an underbar (\texttt{\_}) and - all ASCII letters (a-z and A-Z) are included in the production - for \nonterm{letter}. - Curly brackets, such as $\arbno{x}$, mean an arbitrary number of - (i.e., 0 or more) repetitions of $x$. - Note that curly braces are not terminal symbols in this grammar. - Some character classes are described in English, these are described - in a Roman font between double quotation marks (`` and ''). - Note that all characters matched by the nonterminal - \nonterm{ignored} are ignored by the lexer. - However, the characters that are part of an \nonterm{eol} token - (i.e., carriage returns and newlines) are - not ignored immediately following a semicolon, - \nonterm{reserved-opcode} or \nonterm{reserved-data-size}, although - they are ignored in all other contexts. - } -\label{fig:lexical-grammar} -\end{figure} - -\subsection{Context-Free Grammar} - -The syntax of the SRM's assembly language is defined by the -(context-free) grammar in \figref{fig:cfg}. - -\begin{figure} -\begin{grammar}% -\nonterm{program} \: \nonterm{text-section} \nonterm{data-section} \nonterm{stack-section} .end -\nonterm{text-section} \: .text \nonterm{entry-point} \nonterm{asm-instr} \arbno{\nonterm{asm-instr}} -\nonterm{entry-point} \: \nonterm{addr} -\nonterm{addr} \: \nonterm{label} \| \nonterm{unsigned-number} -\nonterm{label} \: \nonterm{ident} -\nonterm{asm-instr} \: \nonterm{label-opt} \nonterm{instr} \nonterm{eol} -\nonterm{label-opt} \: \nonterm{label}~:~\| \nonterm{empty} -\nonterm{empty} \: -\nonterm{instr} \: \nonterm{three-reg-instr} \| \nonterm{two-reg-instr} \| \nonterm{shift-instr} \| \nonterm{one-reg-instr} -\> \| \> \nonterm{immed-arith-instr} \| \nonterm{immed-bool-instr} \| \nonterm{branch-test-instr} \| \nonterm{load-store-instr} -\> \| \> \nonterm{jump-instr} -\nonterm{three-reg-instr} \: \nonterm{three-reg-op} \nonterm{reg} , \nonterm{reg} , \nonterm{reg} -\nonterm{three-reg-op} \: ADD \| SUB \| AND \| BOR \| NOR \| XOR -\nonterm{two-reg-instr} \: \nonterm{two-reg-op} \nonterm{reg} , \nonterm{reg} -\nonterm{two-reg-op} \: MUL \| DIV -\nonterm{shift-instr} \: \nonterm{shift-op} \nonterm{reg} , \nonterm{reg} , \nonterm{shift} -\nonterm{shift-op} \: SLL \| SRL -\nonterm{shift} \: \nonterm{unsigned-number} -\nonterm{one-reg-instr} \: \nonterm{one-reg-op} \nonterm{reg} -\nonterm{one-reg-op} \: MFHI \| MFLO \| JR -\nonterm{immed-arith-instr} \: \nonterm{immed-arith-op} \nonterm{reg} , \nonterm{reg} , \nonterm{immed} -\nonterm{immed-arith-op} \: ADDI -\nonterm{immed} \: \nonterm{number} -\nonterm{number} \: \nonterm{sign} \nonterm{unsigned-number} -\nonterm{sign} \: + \| - \| \nonterm{empty} -\nonterm{immed-bool-instr} \: \nonterm{immed-bool-op} \nonterm{reg} , \nonterm{reg} , \nonterm{uimmed} -\nonterm{immed-bool-op} \: ANDI \| BORI \| XORI -\nonterm{uimmed} \: \nonterm{unsigned-number} -\nonterm{branch-test-instr} \: \nonterm{branch-test-2-op} \nonterm{reg} , \nonterm{reg} , \nonterm{offset} -\> \| \> \nonterm{branch-test-1-op} \nonterm{reg} , \nonterm{offset} -\nonterm{branch-test-2-op} \: BEQ \| BNE -\nonterm{branch-test-1-op} \: BGEZ \| BGTZ \| BLEZ \| BLTZ -\nonterm{offset} \: \nonterm{number} -\nonterm{load-store-instr} \: \nonterm{load-store-op} \nonterm{reg} , \nonterm{reg} , \nonterm{offset} -\nonterm{load-store-op} \: LBU \| LW \| SB \| SW -\nonterm{jump-instr} \: \nonterm{jump-op} \nonterm{addr} -\nonterm{jump-op} \: JMP \| JAL -\nonterm{syscall-instr} \: \nonterm{syscall-op} -\nonterm{syscall-op} \: EXIT | PSTR | PCH | RCH | RSTR | STRA | NOTR -\nonterm{data-section} \: .data \nonterm{static-start-addr} \arbno{\nonterm{static-decl}} -\nonterm{static-start-addr} \: \nonterm{unsigned-number} -\nonterm{static-decl} \: \nonterm{data-size} \nonterm{ident} \nonterm{initializer-opt} \nonterm{eol} -\nonterm{data-size} \: WORD -\nonterm{initializer-opt} \: = \nonterm{number} \| \nonterm{empty} -\nonterm{stack-section} \: .stack \nonterm{stack-bottom-addr} -\nonterm{stack-bottom-addr} \: \nonterm{unsigned-number}% -\end{grammar} -\caption{ - The (context free) grammar of the SRM assembler, which uses - a \texttt{typewriter font} for terminal symbols. -} -\label{fig:cfg} -\end{figure} - -\section{Initial Values} -\label{sec:initialvalues} - -The initial value of the program counter ($\PC$) is set to the address of the -program's entry point (i.e., the value of \nonterm{entry-point}), -which is declared at the beginning of the \nonterm{text-section}. - -The start of the global data in memory is at the address given by the -data section's static data start address -(i.e., the value of \nonterm{static-start-addr}), declared at the -beginning of the \nonterm{data-section}; -this value is used as the initial value of the $\GP$ register. -The data declared in the data section all have offsets from this -address that are computed in declaration order, with \texttt{WORD} sized data -taking $\WSinBytes$ bytes. -(\texttt{WORD} is the only data size allowed at present.) - -The ``bottom'' of the runtime stack is given in a declaration in -the stack section (\nonterm{stack-section}); -it is the value of \nonterm{stack-bottom-addr} that follows the -\texttt{.stack} keyword. -This must be divisible by $\WSinBytes$ and strictly greater than the -static data start address; it is also the initial value put in -the $\FP$ and $\SP$ registers at the start of a program's execution. - -\section{Constraints on Assembly Code} - -There are some constraints on programs that the assembler checks; -the assembler considers violations of these constraints to be an error. - -The program's entry point (\nonterm{entry-point} value), -static data start address (\nonterm{static-start-addr} value), -and stack bottom address (\nonterm{stack-bottom-addr} value) -must all be divisible by $\WSinBytes$. -Furthermore, the entry point must be strictly less than the static -data start address and the static data strart address must be strictly -less than the stack bottom address. - -% Word-sized data declared in the data section must be aligned; -% that is, the offset of every word declared in the data section -% (the number of bytes past the start of the data section) -% must be divisible by $\WSinBytes$. - -\bibliography{srm-vm.bib} - -\end{document} diff --git a/vm/srm-isa.tex b/vm/srm-isa.tex deleted file mode 100755 index e5f8626..0000000 --- a/vm/srm-isa.tex +++ /dev/null @@ -1,45 +0,0 @@ -% $Id: srm-isa.tex,v 1.3 2023/09/16 12:41:27 leavens Exp $ -% Macros for the ISA follow -\newcommand{\WS}{32} -\newcommand{\WSP}{31} -\newcommand{\WSinBytes}{4} -\newcommand{\LOGofRegs}{5} -\newcommand{\WSminusOP}{26} -\newcommand{\INITIALSTACKBOTTOM}{4096} -\newcommand{\NAMEDREG}[1]{\textsf{\$#1}} -\newcommand{\BP}{\FP} -\newcommand{\GP}{\NAMEDREG{gp}} -\newcommand{\FP}{\NAMEDREG{fp}} -\newcommand{\SP}{\NAMEDREG{sp}} -\newcommand{\RA}{\NAMEDREG{ra}} -\newcommand{\RS}{\NAMEDREG{rs}} -\newcommand{\RT}{\NAMEDREG{rt}} -\newcommand{\RD}{\NAMEDREG{rd}} -\newcommand{\VZERO}{\NAMEDREG{v0}} -\newcommand{\AZERO}{\NAMEDREG{a0}} -\newcommand{\AONE}{\NAMEDREG{a1}} -\newcommand{\ATWO}{\NAMEDREG{a2}} -\newcommand{\GPR}[1]{\textrm{GPR[}#1\textrm{]}} -\newcommand{\IMMED}{\textit{i}} -\newcommand{\OFFSET}{\textit{o}} -\newcommand{\PC}{\textit{PC}} -\newcommand{\HI}{\textit{HI}} -\newcommand{\LO}{\textit{LO}} -\newcommand{\IR}{\textit{IR}} -\newcommand{\SIGNEXTENDNAME}{\textrm{sgnExt}} -\newcommand{\SIGNEXTEND}[1]{\SIGNEXTENDNAME(#1)} -\newcommand{\ZEROEXTENDNAME}{\textrm{zeroExt}} -\newcommand{\ZEROEXTEND}[1]{\ZEROEXTENDNAME(#1)} -\newcommand{\FORMOFFSETNAME}{\textrm{formOffset}} -\newcommand{\FORMOFFSET}[1]{\FORMOFFSETNAME(#1)} -\newcommand{\FORMADDRESSNAME}{\textrm{formAddress}} -\newcommand{\FORMADDRESS}[2]{\FORMADDRESSNAME(#1,#2)} -\newcommand{\MEMORYNAME}{\textrm{memory}} -\newcommand{\MEMORY}[1]{\ensuremath{\MEMORYNAME[#1]}} -\newcommand{\MOD}{\ensuremath{\:\hbox{\%}\:}} -\newcommand{\AND}{\ensuremath{\wedge}} -\newcommand{\OR}{\ensuremath{\vee}} -\newcommand{\XOR}{\ensuremath{\:\textrm{xor}\:}} -\newcommand{\LSHIFT}{\ensuremath{\:\texttt{<<}\:}} -\newcommand{\RSHIFT}{\ensuremath{\:\texttt{>>}\:}} -\newcommand{\GETS}{\ensuremath{\leftarrow}} diff --git a/vm/srm-lexertest1.asm b/vm/srm-lexertest1.asm deleted file mode 100755 index 0355bf4..0000000 --- a/vm/srm-lexertest1.asm +++ /dev/null @@ -1,14 +0,0 @@ -# $Id: srm-lexertest1.asm,v 1.4 2023/09/16 16:23:10 leavens Exp $ - -.text foo -foo: EXIT #some text$a.sa# - ADD $1, $2 , $3 - -.data 1024 -WORD x c -WORD y 42 -.stack 5120 -.end -asdflkasjf -_asb 0x42 - diff --git a/vm/srm-vm.aux b/vm/srm-vm.aux deleted file mode 100755 index 91345f4..0000000 --- a/vm/srm-vm.aux +++ /dev/null @@ -1,91 +0,0 @@ -\relax -\providecommand\hyper@newdestlabel[2]{} -\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument} -\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined -\global\let\oldnewlabel\newlabel -\gdef\newlabel#1#2{\newlabelxx{#1}#2} -\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} -\AtEndDocument{\ifx\hyper@anchor\@undefined -\let\newlabel\oldnewlabel -\fi} -\fi} -\global\let\hyper@last\relax -\gdef\HyperFirstAtBeginDocument#1{#1} -\providecommand\HyField@AuxAddToFields[1]{} -\providecommand\HyField@AuxAddToCoFields[2]{} -\bibstyle{plain} -\citation{Kane-Heinrich92} -\@writefile{toc}{\contentsline {section}{\numberline {1}Overview}{1}{section.1}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {1.1}Inputs and Outputs}{1}{subsection.1.1}\protected@file@percent } -\@writefile{toc}{\contentsline {subsubsection}{\numberline {1.1.1}Binary Object Files}{1}{subsubsection.1.1.1}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{bof.h}{2}{lstlisting.-2}\protected@file@percent } -\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces The \texttt {bof.h} header file that defines the format and operations for binary object files.}}{2}{figure.1}\protected@file@percent } -\newlabel{fig:bofh}{{1}{2}{The \texttt {bof.h} header file that defines the format and operations for binary object files}{figure.1}{}} -\@writefile{toc}{\contentsline {subsubsection}{\numberline {1.1.2}Initial/Default Values}{2}{subsubsection.1.1.2}\protected@file@percent } -\newlabel{sec:initial}{{1.1.2}{2}{Initial/Default Values}{subsubsection.1.1.2}{}} -\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces The layout of a binary object file.}}{3}{figure.2}\protected@file@percent } -\newlabel{fig:boffilelayout}{{2}{3}{The layout of a binary object file}{figure.2}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {1.2}The Running Program's Input and Output}{4}{subsection.1.2}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {1.3}Tracing Output}{4}{subsection.1.3}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {1.4}Printing the Program}{4}{subsection.1.4}\protected@file@percent } -\newlabel{sec:printing}{{1.4}{4}{Printing the Program}{subsection.1.4}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {1.5}Error Outputs}{4}{subsection.1.5}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{vm\textunderscore test0.asm}{5}{lstlisting.-5}\protected@file@percent } -\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces The SRM assembly language file \texttt {vm\_test0.asm}.}}{5}{figure.3}\protected@file@percent } -\newlabel{fig:test0asm}{{3}{5}{The SRM assembly language file \texttt {vm\_test0.asm}}{figure.3}{}} -\@writefile{lol}{\contentsline {lstlisting}{vm\textunderscore test0.out}{5}{lstlisting.-6}\protected@file@percent } -\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces The tracing output of running the VM (with the \texttt {-t} option) on the file \texttt {vm\_test0.bof} (which is the result of using the assembler on \texttt {vm\_test0.asm}), with the command \texttt {./vm vm\_test0.bof}, as would be printed on standard output.}}{5}{figure.4}\protected@file@percent } -\newlabel{fig:test0output}{{4}{5}{The tracing output of running the VM (with the \texttt {-t} option) on the file \texttt {vm\_test0.bof} (which is the result of using the assembler on \texttt {vm\_test0.asm}), with the command \texttt {./vm vm\_test0.bof}, as would be printed on standard output}{figure.4}{}} -\@writefile{lol}{\contentsline {lstlisting}{vm\textunderscore test0.lst}{5}{lstlisting.-7}\protected@file@percent } -\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces The output of running \texttt {./vm -p vm\_test0.bof}. (where the file \texttt {vm\_test0.bof} is the result of assembling the file \texttt {vm\_test0.asm} that is shown in Figure\nobreakspace {}\ref {fig:test0asm}).}}{5}{figure.5}\protected@file@percent } -\newlabel{fig:test0listing}{{5}{5}{The output of running \texttt {./vm -p vm\_test0.bof}. (where the file \texttt {vm\_test0.bof} is the result of assembling the file \texttt {vm\_test0.asm} that is shown in \figref {fig:test0asm})}{figure.5}{}} -\citation{Kane-Heinrich92} -\@writefile{toc}{\contentsline {subsection}{\numberline {1.6}Exit Code}{6}{subsection.1.6}\protected@file@percent } -\@writefile{toc}{\contentsline {section}{\numberline {2}Architecture}{6}{section.2}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Registers}{6}{subsection.2.1}\protected@file@percent } -\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.1}General Purpose Registers and Their Names}{6}{subsubsection.2.1.1}\protected@file@percent } -\@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces SRM Register Numbers, Use, and Names}}{6}{table.1}\protected@file@percent } -\newlabel{tab:registers}{{1}{6}{SRM Register Numbers, Use, and Names}{table.1}{}} -\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.2}Special Purpose Registers}{6}{subsubsection.2.1.2}\protected@file@percent } -\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.3}Calling Convention}{7}{subsubsection.2.1.3}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Binary Instruction Format}{7}{subsection.2.2}\protected@file@percent } -\@writefile{lot}{\contentsline {table}{\numberline {2}{\ignorespaces SRM Instruction Formats}}{7}{table.2}\protected@file@percent } -\newlabel{tab:instrfmts}{{2}{7}{SRM Instruction Formats}{table.2}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Machine Cycles}{7}{subsection.2.3}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.4}Size Limits}{8}{subsection.2.4}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{machine.h}{8}{lstlisting.-8}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {2.5}Invariants}{8}{subsection.2.5}\protected@file@percent } -\@writefile{toc}{\contentsline {section}{\numberline {A}Appendix A}{8}{appendix.A}\protected@file@percent } -\newlabel{appsec:A}{{A}{8}{Appendix A}{appendix.A}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {A.1}Register/Computational Instructions}{9}{subsection.A.1}\protected@file@percent } -\@writefile{lot}{\contentsline {table}{\numberline {3}{\ignorespaces Register Format Instructions}}{9}{table.3}\protected@file@percent } -\newlabel{tab:rformatinstrs}{{3}{9}{Register Format Instructions}{table.3}{}} -\citation{Kane-Heinrich92} -\@writefile{toc}{\contentsline {subsection}{\numberline {A.2}Immediate Type Instructions}{10}{subsection.A.2}\protected@file@percent } -\@writefile{lot}{\contentsline {table}{\numberline {4}{\ignorespaces Immediate format instructions:}}{10}{table.4}\protected@file@percent } -\newlabel{tab:immedinstrs}{{4}{10}{Immediate format instructions:}{table.4}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {A.3}Jump Type Instructions}{10}{subsection.A.3}\protected@file@percent } -\@writefile{lot}{\contentsline {table}{\numberline {5}{\ignorespaces Jump Type Instructions}}{11}{table.5}\protected@file@percent } -\newlabel{tab:jumpinstrs}{{5}{11}{Jump Type Instructions}{table.5}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {A.4}System Calls}{11}{subsection.A.4}\protected@file@percent } -\newlabel{sec:syscall}{{A.4}{11}{System Calls}{subsection.A.4}{}} -\@writefile{lot}{\contentsline {table}{\numberline {6}{\ignorespaces System Calls}}{11}{table.6}\protected@file@percent } -\newlabel{tab:syscalls}{{6}{11}{System Calls}{table.6}{}} -\@writefile{toc}{\contentsline {section}{\numberline {B}Appendix B: Hints}{11}{appendix.B}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {B.1}Overall Structure of the Code}{11}{subsection.B.1}\protected@file@percent } -\@writefile{lof}{\contentsline {figure}{\numberline {6}{\ignorespaces A possible way to represent the memory of the VM, which allows access to the same storage as bytes, words, or binary instructions.}}{12}{figure.6}\protected@file@percent } -\newlabel{fig:memoryrep}{{6}{12}{A possible way to represent the memory of the VM, which allows access to the same storage as bytes, words, or binary instructions}{figure.6}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {B.2}Writing Your Own Tests}{12}{subsection.B.2}\protected@file@percent } -\citation{GNUMake} -\@writefile{toc}{\contentsline {subsection}{\numberline {B.3}Disassembler}{13}{subsection.B.3}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {B.4}Provided Files}{13}{subsection.B.4}\protected@file@percent } -\@writefile{toc}{\contentsline {subsubsection}{\numberline {B.4.1}Makefile}{13}{subsubsection.B.4.1}\protected@file@percent } -\bibdata{srm-vm.bib} -\bibcite{GNUMake}{1} -\@writefile{toc}{\contentsline {subsubsection}{\numberline {B.4.2}C Typedefs for SRM Machine Types}{14}{subsubsection.B.4.2}\protected@file@percent } -\@writefile{toc}{\contentsline {subsubsection}{\numberline {B.4.3}Other modules provided}{14}{subsubsection.B.4.3}\protected@file@percent } -\@writefile{lol}{\contentsline {lstlisting}{machine\textunderscore types.h}{15}{lstlisting.-11}\protected@file@percent } -\@writefile{lof}{\contentsline {figure}{\numberline {7}{\ignorespaces The header file of the \texttt {machine\_types} module, which provides some basic definitions for the VM.}}{15}{figure.7}\protected@file@percent } -\newlabel{fig:machinetypes}{{7}{15}{The header file of the \texttt {machine\_types} module, which provides some basic definitions for the VM}{figure.7}{}} -\bibcite{Kane-Heinrich92}{2} -\gdef \@abspage@last{16} diff --git a/vm/srm-vm.bbl b/vm/srm-vm.bbl deleted file mode 100755 index 07fcfa5..0000000 --- a/vm/srm-vm.bbl +++ /dev/null @@ -1,13 +0,0 @@ -\begin{thebibliography}{1} - -\bibitem{GNUMake} -Free Software Foundation. -\newblock {\em GNU Make Manual}, Feb 2023. -\newblock \url{https://www.gnu.org/software/make/manual/}. - -\bibitem{Kane-Heinrich92} -Gerry Kane and Joe Heinrich. -\newblock {\em {MIPS RISC} architectures}. -\newblock Prentice-Hall, Inc., 1992. - -\end{thebibliography} diff --git a/vm/srm-vm.bib b/vm/srm-vm.bib deleted file mode 100755 index 9b02cf6..0000000 --- a/vm/srm-vm.bib +++ /dev/null @@ -1,15 +0,0 @@ -@book{Kane-Heinrich92, - author={Gerry Kane and Joe Heinrich}, - title={{MIPS RISC} architectures}, - year={1992}, - publisher={Prentice-Hall, Inc.} -} - -@Manual{GNUMake, - title = {GNU Make Manual}, - key = {GNUMake}, - organization = {Free Software Foundation}, - month = {Feb}, - year = 2023, - note = {\url{https://www.gnu.org/software/make/manual/}} -} diff --git a/vm/srm-vm.tex b/vm/srm-vm.tex deleted file mode 100755 index 74d3833..0000000 --- a/vm/srm-vm.tex +++ /dev/null @@ -1,1017 +0,0 @@ -% $Id: srm-vm.tex,v 1.62 2023/11/15 19:41:22 leavens Exp leavens $ -\documentclass[11pt,letterpaper]{article} -\usepackage[T1]{fontenc} -\usepackage{times} -\usepackage{textcomp} %required to set upquote flag and for luximono -%\usepackage[scaled=0.81]{luximono} -\usepackage{enumitem} -\usepackage{listings} -\usepackage{graphics} -\usepackage{color} -\usepackage{ragged2e} -\lstset{language=C,basicstyle=\ttfamily,commentstyle=\rmfamily\itshape} -\lstset{morecomment=[l]{//}, %use comment-line-style! - morecomment=[s]{/*}{*/}} %for multiline comments -\lstset{upquote=true} %FH -% The following is needed for C programs -\lstset{showspaces=false,showstringspaces=false} -%\lstset{mathescape=true} -\input{boxed-figure-new} -% getting files for figures -\newcommand{\LSTFILE}[1]{ -\lstinputlisting[basicstyle=\small\ttfamily]{#1} -} -\newcommand{\LSTFILESLICE}[2]{ -\lstinputlisting[basicstyle=\small\ttfamily,linerange={#1}]{#2} -} -% -\newcommand{\LSTCFILE}[1]{ -\lstinputlisting[language=C,basicstyle=\small\ttfamily]{#1} -} -\newcommand{\LSTCFILESLICE}[2]{ -\lstinputlisting[language=C,basicstyle=\small\ttfamily,linerange={#1}]{#2} -} -\usepackage[bookmarks=false]{hyperref} -%\usepackage{varioref} % doesn't work with hyperref, it seems, sigh -%\renewcommand{\reftextfacebefore}{on the previous page} -%\renewcommand{\reftextfaceafter}{on the next page} -\newcommand{\tabref}[1]{Table~\ref{#1}} % vref from varioref -\newcommand{\tabnref}[1]{Table~\ref{#1}} % doesn't use varioref -\newcommand{\figref}[1]{Figure~\ref{#1}} % vref from varioref -\newcommand{\fignref}[1]{Figure~\ref{#1}} % doesn't use varioref -\newcommand{\secref}[1]{Section~\ref{#1}} % vref from varioref -\newcommand{\secnref}[1]{Section~\ref{#1}} % doesn't use varioref - -\input{obey} -\input{grammar} -\renewcommand{\nonterm}[1]{\mbox{$\langle$\textrm{#1}$\rangle$}} -\renewcommand{\arbno}[1]{\{#1\}} -\newcommand{\gramquote}[1]{\textrm{`}#1\textrm{'}} -\input{use-full-height} -\input{use-full-width} -\input{continuedenum} - -\setlength\RaggedRightParindent{\parindent} -\input{srm-isa.tex} -\newcommand{\IFO}[2]{\textrm{\textbf{if} \ensuremath{#1} \textbf{then} \ensuremath{#2} }} -\newcommand{\IF}[3]{\textrm{\textbf{if} #1 \textbf{then} #2 \textbf{else} #3}} -\newcommand{\EQUALS}{\ensuremath{=}} % or {\ensuremath{\:\texttt{==}\:}} -% -\bibliographystyle{plain} -% -\title{Simplified RISC Machine Manual \\ - (\lstinline!$Revision: 1.62 $!)} -\author{Gary T. Leavens \\ - Leavens@ucf.edu} -\begin{document} - -\maketitle -\begin{abstract} -This document defines the machine code of the Simplified RISC Machine VM for -use in the Systems Software class (COP 3402) at UCF. -\end{abstract} - -\section{Overview} - -The Simplified RISC Machine (SRM) processor's instruction set architecture -(ISA) is simplified from the MIPS processor's ISA \cite{Kane-Heinrich92}. -In particular, SRM is a little-endian machine with $\WS$-bit ($\WSinBytes$-byte) words. -All instructions are also $\WS$-bits wide and there is no floating-point support, kernel mode support, or other advanced features. - -\subsection{Inputs and Outputs} - -\subsubsection{Binary Object Files} - -The VM is passed a single file name on its command line as an -argument. -Optionally the VM be passed a single command line option, either -\texttt{-p} or \texttt{-t}. - -When given a \texttt{-p} argument followed by a binary object file -name, the VM loads the binary object file and prints the assembly -language form of the program, see \secref{sec:printing} details. - -When given a \texttt{-t} argument followed by a binary object file -name, the VM runs the binary object file with tracing output enabled. -By default, no tracing happens, but users can turn on tracing under -program control by executing the \texttt{STRA} system call. - -The remainder of this section is concerned -with what the VM does when it only is given a binary object file name -on its command line as an argument. - -The file name given to the VM must be the name of a (readable) -binary object file containing the program that the VM should execute. -For example, if the VM's executable is named \texttt{vm} and the program it -should run is contained in the file named \texttt{test.bof} -(and both these files are in the current directory), then the VM should -execute the program in the file \texttt{test.bof} by executing -the following command in the Unix shell. - -\begin{lstlisting} - ./vm test.bof -\end{lstlisting} - -The format of a binary object file (BOF) is given in the header file -\texttt{bof.h}, which is shown in part in \figref{fig:bofh}. -A BOF starts the header, then the instructions (also in -binary form) follow, followed by the initial values of data. -This layout of binary object files is shown in \figref{fig:boffilelayout}. - -The header of a binary object file starts with a 4-character field -that contains the characters ``\lstinline!BOF!'' -(and a null character); this kind of ``magic number'' is commonly used -to identify files in Unix. -The magic number is followed (in the BOF header) by the starting address of -the program's code and the length of the program's code (in bytes), which -constitutes the ``text'' section of the binary object file. -These are followed by the starting address of the data section and its -length (in bytes). -The data section contains the global/static variables that the program uses. -Finally, the header contains the initial value for the stack and frame -pointers, which is the address (in bytes) of the bottom of the runtime -stack. - -\begin{figure}[htbp] -\LSTCFILESLICE{1-24,75-76}{bof.h} -\caption{The \texttt{bof.h} header file that defines the format and - operations for binary object files.} -\label{fig:bofh} -\end{figure} - -\begin{figure}[htbp] -\includegraphics*{BOF_layout.png} -\caption{The layout of a binary object file.} -\label{fig:boffilelayout} -\end{figure} - -\subsubsection{Initial/Default Values} -\label{sec:initial} - -The memory of the machine starts at all zero ($0$) values. -Then the instructions specified by the given binary object file -(as named on the command line) are loaded into memory, -starting at address $0$, making the contents of the first $N$ bytes -(where $N$ is divisible by $\WSinBytes$) -of memory be the same as the $N$ bytes following the header itself in -the binary object file; here $N$ is the same as the header's value of -the \lstinline!text_length! field. -Following those $N$ bytes are the bytes of the data section. -These are loaded into the memory starting at the data start address -given in the header; thus any initial values are copied from the -data section of the binary object file into VM's memory. - -When the program starts executing: -\begin{itemize} -\item -the register {\GP} is set to the start address of the data section -given in the header, -which must be divisible by $\WSinBytes$, - -\item -the registers {\FP} and {\SP} are both is set to the stack bottom -address given in the header, which must be divisible by $\WSinBytes$ -and strictly greater than the start address of the data section, - -\item -to simulate a call of the program (by the OS) the {\AZERO} register is -set to the same value as {\FP}, and - -\item -the program counter {\PC} is set to the text section's start address, -which must be divisible by $\WSinBytes$ and strictly less than the -data section's start address. -\end{itemize} - -% \clearpage - -\subsection{The Running Program's Input and Output} - -When the program executes instructions to read or write characters, -these are read from standard input (\texttt{stdin}) and written to -standard output (\texttt{stdout}). - -However, note that if you want the program to read a character, typing a single -character (say \texttt{x}) into the terminal (i.e., to the shell) -while the program is running will not send that character immediately -to the program, as standard input is buffered by default. To send -characters to the program it is best to use a pipe or file redirection -in the Unix shell; for example, to send the two characters \texttt{x} -and \texttt{y} (followed by a newline character) -to the VM running the program \texttt{progfile.bof} one -could use the following command at the Unix shell: - -\begin{lstlisting} - echo xy | ./vm progfile.bof -\end{lstlisting} - -Another command that would accomplish the same thing is to put the -characters to be input into a file (using a text editor), say -\texttt{xy-input.txt} and then to use the following Unix command. - -\begin{lstlisting} - ./vm progfile.bof < xy-input.txt -\end{lstlisting} - -\subsection{Tracing Output} - -When used with the \texttt{-t} option or after the \texttt{STRA} -system call is executed, -the VM produces output that traces the its execution on \texttt{stdout}. -(This tracing output can be turned off under program control -by executing a \texttt{NOTR} system call instruction.) -(See \secref{sec:syscall} for more information about the \texttt{STRA} -and \texttt{NOTR} system call instructions.) - -The tracing output shows the initial state of the VM, then for each -instruction executed, it shows the address (in bytes) of that -instruction and then the assembly language form of that instruction. - -The state of the machine shown in tracing output shows: -the values in the PC, the values of the HI and LO registers (if those -are not zero) and the values in all the general purpose registers, -then the memory starting at the address in $\GPR{\GP}$ -with locations containing zeros only indicated with ``\texttt{...}''. -and then the data between the addresses between $\GPR{\SP}$ and -the stack bottom address specified in the binary object file. -The idea is that those addresses should include the runtime stack. -When showing the memory, locations containing zeros are only -indicated with ``\texttt{...}''. -For example, when the binary object file that is assembled from the -assembly code shown in \figref{fig:test0asm} is executed, -which is found in the file \texttt{vm\_test0.bof}, -it produces the output shown in \figref{fig:test0output}. - -\begin{figure} -\LSTFILE{vm_test0.asm} -\caption{The SRM assembly language file \texttt{vm\_test0.asm}.} -\label{fig:test0asm} -\end{figure} - -\begin{figure} -\lstinputlisting[basicstyle=\ttfamily\scriptsize]{vm_test0.out} -\caption{The tracing output of running the VM (with the \texttt{-t} option) - on the file \texttt{vm\_test0.bof} - (which is the result of using the assembler on \texttt{vm\_test0.asm}), - with the command \texttt{./vm vm\_test0.bof}, - as would be printed on standard output.} -\label{fig:test0output} -\end{figure} - -\subsection{Printing the Program} -\label{sec:printing} - -When the VM is given the argument \texttt{-p} option followed by a -binary object file name, it first loads the instructions and data from the -given binary object file, then it prints what was loaded in assembly -language format, and then the VM exits (without running the program). This -can be helpful for understanding what a program is doing. This output -is shown in \figref{fig:test0listing}. - -\begin{figure} -\LSTFILE{vm_test0.lst} -\caption{The output of running \texttt{./vm -p vm\_test0.bof}. - (where the file \texttt{vm\_test0.bof} is the result of assembling the file - \texttt{vm\_test0.asm} that is shown in \figref{fig:test0asm}).} -\label{fig:test0listing} -\end{figure} - -\subsection{Error Outputs} - -All error messages (e.g., for division by zero) are sent to -standard error output (\texttt{stderr}). - -\subsection{Exit Code} - -When the machine halts normally, it exits with a zero error code -(which indicates success on Unix). However, when the machine -encounters an error it halts and exits with a non-zero exit code -(which indicates failure on Unix). - -\section{Architecture} - -In SRM, words are $\WS$ bits ($\WSinBytes$ bytes). -These bits can be interpreted as an integer or as an address. -The machine is byte addressed but instructions must always be at an -address that is on a word boundary (i.e., whose address is evenly -divisible by $\WSinBytes$). - -\subsection{Registers} - -\subsubsection{General Purpose Registers and Their Names} - -The SRM is a register machine with 32 -general purpose registers\footnote{What we call -``registers'' in this document are simply important concepts that -simulate what would be registers in a hardware implementation of the -virtual machine. For the VM program, these registers would be implemented -as variables.}, -numbered 0 to 31 (inclusive). -These are all $\WS$-bit registers. -Since there are 32 registers, -instructions use $\LOGofRegs$ bits to specify them. - -Register 0 cannot be written to, and when read its value is always 0. - -Conventions (from the MIPS architecture \cite{Kane-Heinrich92}) are -followed for these registers and their names, -as shown in \tabref{tab:registers}. -The names shown in \tabnref{tab:registers} are conventional ones. - -\begin{table}[htb] - \caption{SRM Register Numbers, Use, and Names} - \label{tab:registers} -\begin{center} -\begin{tabular}{| l | l | l |} - \hline - Number & Use & Name\\ - \hline - $0$ & always 0 (can't write to this register!) & \\ - $1$ & assembler temporary & \NAMEDREG{at} \\ - $2-3$ & function results & \NAMEDREG{v0}, \NAMEDREG{v1} \\ - $4-7$ & function arguments & \NAMEDREG{a0}$-$\NAMEDREG{a3} \\ - $8-15$ & temporaries & \NAMEDREG{t0}$-$\NAMEDREG{t7} \\ - $16-23$ & temporaries & \NAMEDREG{s0}$-$\NAMEDREG{s7} \\ - $24-25$ & temporaries & \NAMEDREG{t8}, \NAMEDREG{t9} \\ - $26-27$ & reserved for use by OS (don't use!) & \\ - $28$ & globals pointer & $\GP$ \\ - $29$ & stack pointer & $\SP$ \\ - $30$ & frame pointer & $\FP$ \\ - $31$ & return address & $\RA$ \\ - \hline -\end{tabular} -\end{center} -\end{table} - -\subsubsection{Special Purpose Registers} - -SRM also has a few special registers. The registers are named: - -\begin{itemize} -\item - {\PC}, the program counter which holds the address of the next - instruction to execute, - -\item - {\HI}, the high part (i.e., most significant bits) of the result of a multiplication or the - remainder in a division, - -\item - {\LO}, the low part (i.e., least significant bits) of the result of - a multiplication or the quotient in a division. -\end{itemize} - -The $\PC$ register is manipulated by jump instructions. -The $\HI$ and $\LO$ registers are read by instructions that move their contents into another register. - -\subsubsection{Calling Convention} - -The calling convention on the SRM follows the calling convention on -the MIPS processor. - -That is, the caller must save registers $1-15$, and $24-25$ -if they will be needed after a call (and then restores them when -needed). - -The callee saves (and restores before it returns) registers $16-23$ -and $29-31$, if it uses (writes) them. - -(Furthermore, register $0$ cannot be changed and registers $1$ and -$28$ should not be changed by a hand-written routine. -Registers $26-27$ should not be changed by user code.) - -Note that the jump-and-link (\texttt{JAL}) instruction -does not save any registers except the $\PC$, -and it will save that in register $31$. - -\subsection{Binary Instruction Format} - -In object code, -all instructions are one word long and start with a 6-bit opcode. -However, instructions may have one of several formats, with the format -depending on the opcode (called ``op'' below). -The fields of each instruction format shown in \tabref{tab:instrfmts} -are followed by their width in bits; -for example the op field is 6 bits wide. - -\begin{table}[htb] - \caption{SRM Instruction Formats} - \label{tab:instrfmts} -\begin{itemize} -\item Register/computational type instruction format: \\ -\begin{tabular}{|c|p{6ex}{c}|p{6ex}{c}|p{6ex}{c}|p{10ex}|p{9ex}|} - \hline - op:6 & \multicolumn{1}{|c|}{rs:5} & \multicolumn{1}{|c|}{rt:5} & \multicolumn{1}{|c|}{rd:5} & \multicolumn{1}{|c|}{shift:5} & \multicolumn{1}{|c|}{func:6} \\ - \hline -\end{tabular} - -\item System call instructions, whose format is a variant of the register type -instruction format, but with a func field value of 12: \\ -\begin{tabular}{|c|p{6ex}{c}|p{6ex}{c}|p{6ex}{c}|p{10ex}|p{9ex}|} - \hline - op:6 & \multicolumn{4}{|c|}{~~~~~~~~~~~~~code:20~~~~~~~~~~~~~~~~} & \multicolumn{1}{|c|}{func:6} \\ - \hline -\end{tabular} - -\item -Immediate operand type instruction format: \\ -\begin{tabular}{| c | p{6ex}{c} | p{6ex}{c} | p{16ex} |} - \hline - op:6 & \multicolumn{1}{|c|}{rs:5} & \multicolumn{1}{|c|}{rt:5} & \multicolumn{1}{c|}{~~~~~~~~~immed:16~~~~~~~~~~~} \\ - \hline -\end{tabular} - -\item -Jump type instruction format: \\ -\begin{tabular}{| c | p{26ex}|} - \hline - op:6 & \multicolumn{1}{c|}{~~~~~~~~~~~~~~~~~~~~~addr:26~~~~~~~~~~~~~~~~~~~~~~~} \\ - \hline -\end{tabular} -\end{itemize} -\end{table} - -The list of instructions and details on their execution appears in -Appendix \ref{appsec:A}. - -\subsection{Machine Cycles} - -The SRM instruction cycle conceptually does the following for each -instruction: - -\begin{enumerate} -\item - Let $\IR$ be the instruction at the location that {\PC} indicates. - (Note that $\IR$ could be considered to be the contents of a register.) - -\item - The {\PC} is made to point to the next instruction - (i.e., it is set to the address $\PC + \WSinBytes$). - -\item - Then the instruction in $\IR$ is executed. - The op component of this instruction ($\IR$.op) indicates the operation - to be executed. - For example, if $\IR$.op encodes the instruction JR, - then the machine jumps to the specified address by - setting the $\PC$ register (to the contents of the given register). -\end{enumerate} - -\subsection{Size Limits} - -The following constant defines the size of the memory for the VM. - -\LSTCFILESLICE{10-10}{machine.h} - -You might need to copy this definition into your program. - -Note that \lstinline!BYTES_PER_WORD! is defined to be 4 in -\lstinline!machine_types.h!, see \figref{fig:machinetypes}. - -\subsection{Invariants} - -The VM enforces the following invariants and will halt with an error -message (written to stderr) if one of them is violated: - -\newcommand{\BPW}{\mbox{\texttt{BYTES\_PER\_WORD}}} -\begin{itemize} -\item - $\PC \MOD \BPW = 0$, - -\item - $\GPR{\GP} \MOD \BPW = 0$, - -\item - $\GPR{\SP} \MOD \BPW = 0$, - -\item - $\GPR{\FP} \MOD \BPW = 0$, - -\item - $0 \leq \GPR{\GP}$, - -\item - $\GPR{\GP} < \GPR{\SP}$, - -\item - $\GPR{\SP} \leq \GPR{\FP}$, - -\item - $\GPR{\FP} < \mbox{\texttt{MEMORY\_SIZE\_IN\_BYTES}}$, - -\item - $0 \leq \PC$, - -\item - $\PC < \mbox{\texttt{MEMORY\_SIZE\_IN\_BYTES}}$, and - -\item - $\GPR{0} = 0$. -\end{itemize} - -\appendix -\section{Appendix A} -\label{appsec:A} - -In the following tables, italicized names (such as $s$) are -meta-variables that refer to integers. -If an instruction's field is -notated as $-$, then its value does not matter (we use $0$ as a -placeholder for such values in examples). - -All numbers appearing in the following table are in decimal (base 10) notation. - -\subsection{Register/Computational Instructions} - -Note that all of the instructions in table \tabref{tab:rformatinstrs} -have an opcode of $0$, -and a function specified by the func field. They each also have 3 register -arguments: rs, rt, and rd. -The contents of the general purpose register $r$ is -notated as $\GPR{r}$ in the table. -All numbers in the table are in decimal notation. - -All arithmetic and logical operations are performed as for C -\textbf{int} values. -However, the right shift works on the contents of the register -$\GPR{t}$ in a logical manner, as if it were an \textbf{unsigned int}, -so it should shift in zeros from the left. - - -\begin{table}[htbp] -\caption{Register Format Instructions} -\label{tab:rformatinstrs} -\begin{tabular}{|l|l|c|c|c|c|l|p{9cm}|} -\hline -~ & ~ & ~ & ~ & ~ & ~ & & Comment \\ -Name & op & rs & rt & rd & shift & func & (Explanation) \\ -\hline -ADD & 0 &$s$ &$t$ &$d$ & - & 33 & Add: $\GPR{d} \GETS \GPR{s} + \GPR{t}$ \\ -\hline -SUB & 0 &$s$ &$t$ &$d$ & - & 35 & Subtract: $\GPR{d} \GETS \GPR{s} - \GPR{t}$ \\ -\hline -MUL & 0 &$s$ &$t$ & - & - & 25 & Multiply: Multiply -$\GPR{s}$ and $\GPR{t}$, \\ -& & & & & & & putting the least significant bits in $\LO$ \\ -& & & & & & & and the most significant bits in $\HI$. \\ -& & & & & & & $(\HI,\LO) \GETS \GPR{s} \times \GPR{t}$ \\ -\hline -DIV & 0 &$s$ &$t$ & - & - & 27 & Divide (remainder in $\HI$, quotient in $\LO$): \\ - & & & & & & & $\HI \GETS \GPR{s} \MOD \GPR{t}$ \\ - & & & & & & & $\LO \GETS \GPR{s} / \GPR{t})$ \\ -\hline -MFHI & 0 & - & - & $d$ & - & 16 & Move from HI: $\GPR{d} \GETS \HI$ \\ -\hline -MFLO & 0 & - & - & $d$ & - & 18 & Move from LO: $\GPR{d} \GETS \LO$ \\ -\hline -AND & 0 &$s$ &$t$ & $d$ & - & 36 & Bitwise And: $\GPR{d} \GETS \GPR{s} \AND \GPR{t}$ \\ -\hline -BOR & 0 &$s$ &$t$ & $d$ & - & 37 & Bitwise Or: $\GPR{d} \GETS \GPR{s} \OR \GPR{t}$ \\ -\hline -NOR & 0 &$s$ &$t$ & $d$ & - & 39 & Bitwise Not-Or: $\GPR{d} \GETS \neg(\GPR{s} \OR \GPR{t})$ \\ -\hline -XOR & 0 &$s$ &$t$ & $d$ & - & 38 & Bitwise Exclusive-Or: $\GPR{d} \GETS \GPR{s} \XOR \GPR{t}$ \\ -\hline -SLL & 0 & - &$t$ & $d$ & $h$ & 0 & Shift Left Logical: $\GPR{d} \GETS \GPR{t} \LSHIFT h$ \\ -\hline -SRL & 0 & - &$t$ & $d$ & $h$ & 3 & Shift Right Logical: $\GPR{d} \GETS \GPR{t} \RSHIFT h$ \\ -\hline -JR & 0 &$s$ & 0 & 0 & 0 & 8 & Jump Register: $\PC \GETS \GPR{s}$ \\ -\hline -SYSCALL & 0 & - & - & - & - & 12 & System Call: (see \tabref{tab:syscalls}) \\ -\hline -\end{tabular} -\end{table} - -\newpage - -\subsection{Immediate Type Instructions} - -The instructions in \tabref{tab:immedinstrs} may have up to 2 register -arguments, and all have an immediate operand, which is a 16 bit value. - -For arithmetic operations, the immediate value is sign-extended (to an -\textbf{int} value), -which is written in the explanations using the function ``{\SIGNEXTENDNAME}.'' -For example, suppose $i$ is $-1$, which is FFFF in hexadecimal -notation; -then $\SIGNEXTEND{i}$ is FFFFFFFF in hexadecimal, which still -represents $-1$. - -However, for logical operations, the immediate value is zero-extended, -which is written in the explanations using the function ``{\ZEROEXTENDNAME}.'' -For example, suppose $i$ is $-1$, which is FFFF in hexadecimal -notation; -then $\ZEROEXTEND{i}$ is 0000FFFF in hexadecimal notation. - -For the branches, the immediate value, $o$ is first shifted left 2 -bits (multiplied by 4) and then sign-extended, which is written as -``{\FORMOFFSETNAME}'' in the table. -(Thus $\FORMOFFSET{o} = \SIGNEXTEND{4 \times o}$.) -Note that the resulting address is added to the address of the -instruction following the currently executing instruction, not the -address of the instruction itself, since the $\PC$ has already been advanced. -(As a simplification, the opcode for the BLTZ instruction is different -from that found in the MIPS architecture \cite{Kane-Heinrich92}.) - -For loads and stores, $\MEMORY{a}$ denotes the contents of the -machine's memory at the byte address $a$. - -\begin{table}[htbp] -\caption{Immediate format instructions:} -\label{tab:immedinstrs} -\begin{tabular}{|l|r|c|c|c|p{11cm}|} -\hline -~ & & ~ & ~ & ~ & Comment \\ -Name & op & rs & rt & immed & (Explanation) \\ -\hline -ADDI & 9 &$s$ &$t$ & $i$ & Add immediate: $\GPR{t} \GETS \GPR{s} + \SIGNEXTEND{i}$ \\ -\hline -ANDI & 12 &$s$ &$t$ & $i$ & Bitwise And immediate: $\GPR{t} \GETS \GPR{s} \AND \ZEROEXTEND{i}$ \\ -\hline -BORI & 13 &$s$ &$t$ & $i$ & Bitwise Or immediate: $\GPR{t} \GETS \GPR{s} \OR \ZEROEXTEND{i}$ \\ -\hline -XORI & 14 &$s$ &$t$ & $i$ & Bitwise Xor immediate: $\GPR{t} \GETS \GPR{s} \XOR \ZEROEXTEND{i}$ \\ -\hline -BEQ & 4 &$s$ &$t$ & $o$ & Branch on Equal: $\IFO{\GPR{s} = \GPR{t}}{\PC \GETS \PC + \FORMOFFSET{o}}$ \\ -\hline -BGEZ & 1 &$s$ & 1 & $o$ & Branch $\geq$ 0: $\IFO{\GPR{s} \geq 0}{\PC \GETS \PC + \FORMOFFSET{o}}$ \\ -\hline -BGTZ & 7 &$s$ & 0 & $o$ & Branch $>$ 0: $\IFO{\GPR{s} > 0}{\PC \GETS \PC + \FORMOFFSET{o}}$ \\ -\hline -BLEZ & 6 &$s$ & 0 & $o$ & Branch $\leq$ 0: $\IFO{\GPR{s} \leq 0}{\PC \GETS \PC + \FORMOFFSET{o}}$ \\ -\hline -BLTZ & 8 &$s$ & 0 & $o$ & Branch $<$ 0: $\IFO{\GPR{s} < 0}{\PC \GETS \PC + \FORMOFFSET{o}}$ \\ -\hline -BNE & 5 &$s$ &$t$ & $o$ & Branch Not Equal: $\IFO{\GPR{s} \neq \GPR{t}}{\PC \GETS \PC + \FORMOFFSET{o}}$ \\ -\hline -LBU & 36 &$b$ &$t$ & $o$ & Load Byte Unsigned: \\ - & & & & & $\GPR{t} \GETS \ZEROEXTEND{\MEMORY{\GPR{b} + \FORMOFFSET{o}}}$ \\ -\hline -LW & 35 &$b$ &$t$ & $o$ & Load Word ($\WSinBytes$ bytes): \\ - & & & & & $\GPR{t} \GETS \MEMORY{\GPR{b} + \FORMOFFSET{o}}$ \\ -\hline -SB & 40 &$b$ &$t$ & $o$ & Store Byte (least significant byte of $\GPR{t}$): \\ - & & & & & $\MEMORY{\GPR{b} + \FORMOFFSET{o}} \GETS \GPR{t}$ \\ -\hline -SW & 43 &$b$ &$t$ & $o$ & Store Word ($\WSinBytes$ bytes): \\ - & & & & & $\MEMORY{\GPR{b} + \FORMOFFSET{o}} \GETS \GPR{t}$ \\ -\hline -\end{tabular} -\end{table} - -\subsection{Jump Type Instructions} - -The instructions in \tabref{tab:jumpinstrs} have a $\WSminusOP$-bit field ``addr'' -which is used to form the address to jump to. -Forming this address is done by left-shifting the given ``addr'' -field, $a$, by 2 bits, -and then concatenating the (4) high bits of the $\PC$ with those -$\WSminusOP+2$ bits to form a $\WS$-bit address. -This is written ``$\FORMADDRESS{\PC,a}$'' in the table. -For example if $a$ is DECADE in hexadecimal notation, and $\PC$ is -FFFACADE in hexadecimal notation, then $\FORMADDRESS{\PC}{a}$ is F37B2B78 -in hexadecimal notation. (Note: if the high-order 4 bits of $\PC$ -are 0, then $\FORMADDRESS{PC}{a}$ is equivalent to left-shifting $a$ -by 2 bits.) - -\begin{table}[htbp] -\caption{Jump Type Instructions} -\label{tab:jumpinstrs} -\begin{tabular}{|r|l|l|p{11cm}|} -\hline -~ & ~ & ~ & Comment \\ -Name & op & addr & (Explanation) \\ -\hline -JMP & 2 & a & Jump: $\PC \GETS \FORMADDRESS{PC}{a}$ \\ -\hline -JAL & 3 & a & Jump and Link: $\GPR{\RA} \GETS \PC; \PC \GETS \FORMADDRESS{\PC}{a}$ \\ -\hline -\end{tabular} -\end{table} - -The Jump and Link (JAL) instruction does a subroutine call. It does -not explicitly manipulate the runtime stack. -% [[[Put more in about calling conventions here.]]] - -\subsection{System Calls} -\label{sec:syscall} - -System calls are used to provide operating system services. -System calls are made by instructions with op 0 and func 12 having the -following format (with code field made of the 20 bits of what would -be the rs, rt, rd, and shift fields of a register type instruction, -all combined). -The code field is used to specify the service requested. - -System calls include exiting a program and various kinds of printing -and reading of character data (bytes). -These are described in \tabref{tab:syscalls}, -using C library equivalents. -In the table, an entry of $-$ means that the contents of argument registers -is not specified. -Otherwise, the contents of particular argument registers are used to -pass actual arguments to the system calls (the program must load the -actual argument values into those registers before making the call). -(Recall that the correspondence between named registers and register -numbers is given in \tabref{tab:registers}.) -All printing done by these instructions -is to the VM's standard output (stdout) and -reading is from the VM's standard input (stdin). - -\begin{table}[htbp] -\caption{System Calls} -\label{tab:syscalls} -\begin{tabular}{|l|l|l|l|} -\hline -code & name & arg. reg. & Effect (in terms of C std. library) \\ -\hline -10 & EXIT & - & \texttt{exit(0) // halt} \\ -\hline - 4 & PSTR & \AZERO & $\GPR{\VZERO} \GETS $ \texttt{printf("\%s",\&$\MEMORY{\GPR{\AZERO}}$)} \\ -\hline - 5 & PINT & \AZERO & $\GPR{\VZERO} \GETS $ \texttt{printf("\%d",\GPR{\AZERO})} \\ -\hline -11 & PCH & \AZERO & $\GPR{\VZERO} \GETS $\texttt{fputc($\GPR{\AZERO}$,stdout)} \\ -\hline -12 & RCH & - & $\GPR{\VZERO} \GETS $ \texttt{getc(stdin)} \\ -\hline -256 & STRA & - & \textrm{start VM tracing; start tracing output} \\ -\hline -257 & NOTR & - & \textrm{no VM tracing; stop the tracing output} \\ -\hline -\end{tabular} -\end{table} - -In the PSTR instruction, the C standard library function -\texttt{printf} will expect a C pointer to characters as its -argument; this should be the address of those character's -representations in the memory starting at the VM address given by the -contents of $\GPR{\AZERO}$. - -\section{Appendix B: Hints} - -\subsection{Overall Structure of the Code} - -To implement the SRM VM, the first thing to do is to decide on some -data structures to represent the VM's state: especially the memory and -registers. You may want to represent the VM's memory using a -definition like that in \figref{fig:memoryrep}. -\begin{figure}[hbtp] -\begin{lstlisting} -#include "machine_types.h" -#include "instruction.h" -// a size for the memory (2^16 bytes = 64K) -#define MEMORY_SIZE_IN_BYTES (65536 - BYTES_PER_WORD) -#define MEMORY_SIZE_IN_WORDS (MEMORY_SIZE_IN_BYTES / BYTES_PER_WORD) - -static union mem_u { - byte_type bytes[MEMORY_SIZE_IN_BYTES]; - word_type words[MEMORY_SIZE_IN_WORDS]; - bin_instr_t instrs[MEMORY_SIZE_IN_WORDS]; -} memory; -\end{lstlisting} -\caption{A possible way to represent the memory of the VM, which - allows access to the same storage as bytes, words, or binary instructions.} -\label{fig:memoryrep} -\end{figure} -With this definition, -the VM's memory is represented as 3 arrays that share the same -storage: \lstinline!memory.bytes!, \lstinline!memory.words!, and -\lstinline!memory.instrs!. For example, -the 4 bytes at byte address 36 can be accessed as -\lstinline!memory.bytes[36]! -or as \lstinline!memory.words[9]! or as \lstinline!memory.instrs[9]!. -This union definition allows VM's code to decide what view it wants -of the storage at each point in the implementation, -and whatever is changed in that view is -seen by all the other views. -Using a union in this way avoids lots of casting and bit manipulation. -Note that the C compiler considers \lstinline!memory.bytes! to have -the type \lstinline!byte_type[]!, -and \lstinline!memory.words! to have the type \lstinline!word_type[]!, -and \lstinline!memory.instrs! to have the type \lstinline!bin_instr_t[]!. - -The registers can be \lstinline!word_type! variables -(where \lstinline!word_type! is defined in -\lstinline!machine_types.h!), -or an array of them. - -Once the representation for memory and the registers is settled, -implement the loading process and get the \texttt{-p} option to work. -There is code in the disassembler that can be used as a model of what -to do. - -To read from the binary object files (BOFs) you should use the -functions in the bof module. -In particular, use \lstinline!bof_read_open! to open such a file, -use \lstinline!bof_read_header! to read and return the header from a -BOF, then read each of the instructions using -\lstinline!instruction_read! (from the instruction module), -and \lstinline!bof_read_word! to read words in the data section of -the BOF. - -You will find the function \lstinline!instruction_assembly_form! -from the instruction module -helpful in doing the printing of instructions. See the code in the -disassembler (\texttt{disasm.c} in particular) for a model of how to -use it. - -After getting the \texttt{-p} option to work, -you need to implement the basic fetch-execute cycle for the VM -(without the \texttt{-p} option): -make a function that executes a single instruction and handles the tracing -and call the function to execute each instruction in a loop. - -To implement the function that executes a single instruction, -have that function decide between the possible instructions -(using the functions from the instruction module) and -in each case carry out the effect of the instruction as described in -the ``Simplified RISC Machine Manual'', which is available on -Webcourses. -You can see the provided code in the -\lstinline!instruction_assembly_form! -function in the instruction module as an example of how to -decide what an instruction is. - -\subsection{Writing Your Own Tests} - -It is often helpful to write your own tests to execute just one or two -instructions during testing of the VM. -However, be sure to include an \texttt{EXIT} instruction in your test to -stop your program's execution! - -To write your own tests you can use the provided assembler, -since the VM only takes binary object files as inputs. - -The SRM assembler can be compiled using the provided Makefile and the -following command. -\begin{lstlisting} -make asm -\end{lstlisting} - -We also provide documentation for the -assembly language in the course files on webcourses; see the file -named ``\texttt{srm-asm.pdf}''. - -\subsection{Disassembler} - -We also provide a disassembler, that does something similar to running the -virtual machine with the \texttt{-p} option; this program can be built -using the Makefile by issuing the command \texttt{make disasm}. -The way that the disassembler does its output, using the -\texttt{instruction} module, can be helpful in writing the code for -the \texttt{-p} option of the VM. - -\subsection{Provided Files} - -We provide all the source files used to build the assembler and the -disassembler. Many of these can be helpful in writing your VM -implementation. The following describes some of these. - -\subsubsection{Makefile} - -The provided \texttt{Makefile} describes how to compile and link programs -and run tests. This \texttt{Makefile} tells the GNU program -\texttt{make} \cite{GNUMake} -about dependencies between files that \texttt{make} uses -to decide when targets need to be built. - -You should edit the Makefile's definition of \texttt{VM\_OBJECTS}; -change that to be a complete list of the \texttt{.o} files -that are needed to build your virtual machine. -The list present in the Makefile for \texttt{VM\_OBJECTS} -is what the course staff used, -but you might, for example, combine the main function, -which was in our files \texttt{machine\_main.c} and -\texttt{machine.c} (none of these are provided to you) -into a single file named \texttt{vm.c}, in which case would replace -our \texttt{machine\_main.o} and \texttt{machine.o} with your \texttt{vm.o} -On the other hand, you will need to leave the object file names in the -list that your code uses, such as \texttt{bof.o} and \texttt{utilities.o}. -If you receive an error message from the Unix linker/loader -(\texttt{ld}) about an ``undefined reference'' to a function or a -piece of data, then the solution is likely to include the relevant -object file in the list of \texttt{VM\_OBJECTS}. - -You should not need to edit anything in the bottom half of the -Makefile, which is the ``developer's section'' used by the course staff. - -There are several useful targets in the Makefile that can be used with -the \texttt{make} command. A \emph{target} is a name given on the -command line to \texttt{make}; for example \texttt{vm} is a target, -and running the command \texttt{make vm} should compile and link the -code needed to build your VM and create an executable program in the -file \texttt{vm} (or \texttt{vm.exe} on Windows). The following is a -list of the targets in the Makefile that may be useful. - -\newcommand{\bft}[1]{\textbf{\texttt{#1}}} -\begin{description} -\item{\bft{file.o}} compiles \texttt{file.c} if it (or \texttt{file.h}) is - newer than \texttt{file.o}, producing a new copy of \texttt{file.o}. - This works for any file name not just ``\texttt{file}'', as the - Makefile has a general rule to compile \texttt{.c} files into - \texttt{.o} files. - -\item{\bft{vm}} compiles (if necessary) all the .o files named in the macro - \texttt{VM\_OBJECTS} and links them together into an executable - named \texttt{vm} (or \texttt{vm.exe} on Windows). - -\item{\bft{vm\_test1.myo}} runs your virtual machine program (\texttt{./vm}) - on the input \texttt{vm\_test1.bof} and sends the (standard) output - (and standard error output) to \texttt{vm\_test1.myo}. - This works for any test file, not just ``\texttt{vm\_test1.bof}'' as - the Makefile has a general rule for this. - -\item{\bft{vm\_test1.myp}} runs your virtual machine program (\texttt{./vm}) - with the \texttt{-p} option on the input \texttt{vm\_test1.bof} - and sends the (standard) output - (and standard error output) to \texttt{vm\_test1.myp}. - This works for any test file, not just ``\texttt{vm\_test1.bof}'' as - the Makefile has a general rule for this. - -\item{\bft{check-vm-outputs}} runs all of the provided tests in the - \texttt{.bof} files and produces the corresponding \texttt{.myo} - files using your VM (in \texttt{./vm}), and compares each one to the - expected output in the corresponding \texttt{.out} file using the - \texttt{diff} command. Each such test passes if no differences are detected. - -\item{\bft{check-lst-outputs}} runs all of the provided tests in the - \texttt{.bof} files and produces the corresponding \texttt{.myp} - files using your VM (as \texttt{./vm -p}), and compares each one to the - expected output in the corresponding \texttt{.lst} file using the - \texttt{diff} command. Each such test passes if no differences are detected. - -\item{\bft{check-outputs}} runs all of the provided tracing and listing - tests (using the targets - \texttt{check-lst-outputs} and \texttt{check-vm-outputs}). - -\item{\bft{submission.zip}} runs all of the provided tests (using the - \texttt{check-outputs} target) and creates a zip file that can be - submitted for the assignment including your code and outputs from - the tests. - -\item{\bft{clean}} removes all the compiled object files (\texttt{*.o}) and testing - output files (\texttt{*.myo} and \texttt{*.myp}) as well as the - executable VM (files named \texttt{vm} and \texttt{vm.exe}) and the - submission zip file (\texttt{submission.zip}). This allows you to - start over from scratch, forcing \texttt{make} to build the do the - work specified for the targets given, instead of thinking that they - are up to date. (This is especially useful if some dependencies are - not captured in the Makefile.) -\end{description} - -\subsubsection{C Typedefs for SRM Machine Types} - -We provide a module, \lstinline!machine_types! (the header -\lstinline!machine_types.h! is shown in \figref{fig:machinetypes}), -which defines some C equivalents for important types of data in the SRM. - -\begin{figure} -\LSTCFILE{machine_types.h} -\caption{The header file of the \texttt{machine\_types} module, which - provides some basic definitions for the VM.} -\label{fig:machinetypes} -\end{figure} - -\subsubsection{Other modules provided} - -The following gives a brief summary of the other provided code -modules, each of which consists of a \texttt{.c} file and a -\texttt{.h} file. - -\begin{itemize} -\item - \lstinline!bof!, which describes binary object files, - -\item - \lstinline!file_location!, which groups file names and line numbers, - -\item - \lstinline!instruction!, which describes machine instructions and - provides several useful utilities for creating and printing - instructions, - -\item - \lstinline!regname!, which provides access to the symbolic names of - the SRM's general purpose registers, - -\item - \lstinline!utilities!, which describes several functions for error - output, including \lstinline!bail_with_error!. -\end{itemize} - -In addition, we provide code to build the assembler (including many of -the above and also the files -\lstinline!asm_main.c!, \lstinline!asm.y!, \lstinline!asm_lexer.l!, -\lstinline!asm_unparser.[ch]!, \lstinline!ast.[ch]!, -\lstinline!lexer.[ch]!, \lstinline!pass1.[ch]!, -\lstinline!assemble.[ch]!, and \lstinline!id_attrs!) -and the disassembler (including many mentioned above and also -\lstinline!disasm_main.c!, \lstinline!disasm.[ch]!). - -You can use any of these provided files in your solution. - -\bibliography{srm-vm.bib} - -\end{document} diff --git a/vm/ssm-asm.pdf b/vm/ssm-asm.pdf deleted file mode 100755 index 7701239..0000000 Binary files a/vm/ssm-asm.pdf and /dev/null differ diff --git a/vm/ssm-vm.pdf b/vm/ssm-vm.pdf deleted file mode 100755 index a991ab3..0000000 Binary files a/vm/ssm-vm.pdf and /dev/null differ diff --git a/vm/symtab.c b/vm/symtab.c deleted file mode 100755 index 1868a3c..0000000 --- a/vm/symtab.c +++ /dev/null @@ -1,131 +0,0 @@ -/* $Id: symtab.c,v 1.4 2024/07/26 12:44:46 leavens Exp $ */ -#include -#include -#include -#include "symtab.h" -#include "utilities.h" - -// For a data structure, we use an array (for now), -// although a hash table might be better... - -// size is also the index of the next element to allocate -static int size; -// The data structure is such that the first size entries contain actual data -static id_attrs_assoc entries[MAX_SYMTAB_SIZE]; - -// The symbol table's invariant -void symtab_okay() -{ - assert(0 <= size); - assert(size < MAX_SYMTAB_SIZE); - for (int i = size; i < MAX_SYMTAB_SIZE; i++) { - assert(entries[i].name == NULL); - } -} - -// initialize the symbol table -void symtab_initialize() -{ - size = 0; // no data yet - id_attrs_assoc none; - none.name = NULL; - none.file_loc = NULL; - none.addr = 0; - for (int i = 0; i < MAX_SYMTAB_SIZE; i++) { - entries[i] = none; - } - symtab_okay(); -} - -// Return the number of mappings in this symbol table -unsigned int symtab_size() { return size; } - -// Is this symbol table empty? (I.e., does it have not mappings?) -bool symtab_empty() { return size == 0; } - -// Is this symbol table full? (I.e., can it not hold more mappings?) -// (i.e., is symtab_size() equal to MAX_SYMTAB_SIZE-1)? -bool symtab_full() { return size >= MAX_SYMTAB_SIZE; } - -// Is the given name associated with some attributes? -bool symtab_defined(const char *name) -{ - id_attrs_assoc *v = symtab_lookup(name); - return v != NULL; -} - -// Requires: !symtab_full -// Requires: !symtab_defined(attrs.name) -// Remember the given attributes (i.e., an association from attrs.name -// to the other parts of attrs) -void symtab_insert(id_attrs_assoc attrs) -{ - if (symtab_full()) { - bail_with_error("The symtab is full!"); - } - entries[size++] = attrs; -} - -// if name == NULL or if name is not defined, return -1 -// if name is defined in the table, return its index -static int find_index(const char *name) -{ - if (name == NULL) { - return -1; - } - for (int i = 0; i < size; i++) { - if (strcmp(entries[i].name, name) == 0) { - return i; - } - } - return -1; -} - - -// Return (a pointer to) the attributes of the given name -// or NULL if there is no association for that name. -id_attrs_assoc *symtab_lookup(const char *name) -{ - int i = find_index(name); - if (0 <= i) { - return &entries[i]; - } else { - return NULL; - } -} - -// iteration helpers -// iterations use an external key which is a name - -// Start an iteration by returning the first name in the symbol table, -// return NULL if symtab_empty() -const char *symtab_first_name() -{ - if (symtab_empty()) { - return NULL; - } - assert(0 < size); - return entries[0].name; -} - -// Are there more names defined in the symbol table after the given one? -// This returns false if name is NULL, if name is not defined, -// or if there are no more names following name in the symbol table -bool symtab_more_after(const char *name) -{ - int i = find_index(name); - return (0 <= i && i < size); -} - -// Requires: symtab_more_after(name); -// Return the next name defined in the symbol table after the given one, -// but return NULL if there are no more names -const char *symtab_next_name(const char *name) -{ - int i = find_index(name); - if (i < 0 || i >= size) { - return NULL; - } else { - return entries[i+1].name; - } -} diff --git a/vm/symtab.h b/vm/symtab.h deleted file mode 100755 index 63a95fb..0000000 --- a/vm/symtab.h +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: symtab.h,v 1.3 2024/07/26 12:44:46 leavens Exp $ */ -#ifndef _SYMTAB_H -#define _SYMTAB_H - -#include -#include "id_attrs_assoc.h" - -// Maximum number of names/attributes that can be stored in a symboltable -#define MAX_SYMTAB_SIZE 1024 - -// initialize the symbol table -extern void symtab_initialize(); - -// Return the number of mappings in this symbol table -extern unsigned int symtab_size(); - -// Is this symbol table empty? (I.e., does it have not mappings?) -extern bool symtab_empty(); - -// Is this symbol table full? (I.e., can it not hold more mappings?) -// (i.e., is symtab_size() equal to MAX_SYMTAB_SIZE-1)? -extern bool symtab_full(); - -// Is the given name associated with some attributes? -extern bool symtab_defined(const char *name); - -// Requires: !symtab_full -// Requires: !symtab_defined(attrs.name) -// Remember the given attributes (i.e., an association from attrs.name -// to the other parts of attrs) -extern void symtab_insert(id_attrs_assoc attrs); - -// Return a pointer to the attributes of the given name -// or NULL if there is no association for that name. -extern id_attrs_assoc *symtab_lookup(const char *name); - -// Start an iteration by returning the first name in the symbol table, -// return NULL if symtab_empty() -extern const char *symtab_first_name(); - -// Are there more names defined in the symbol table after the given one? -// This returns false if name is NULL. -extern bool symtab_more_after(const char *name); - -// Requires: symtab_more_after(name); -// Return the next name defined in the symbol table after the given one, -// but return NULL if there are no more names -extern const char *symtab_next_name(const char *name); -#endif diff --git a/vm/symtab_test4.asm b/vm/symtab_test4.asm deleted file mode 100755 index 2d8978a..0000000 --- a/vm/symtab_test4.asm +++ /dev/null @@ -1,46 +0,0 @@ - # $Id: symtab_test4.asm,v 1.2 2024/08/28 21:25:00 leavens Exp $ - .text start -start: NOTR - STRA - ADDI $0, $t0, 5 # $t0 is 5 - ADDI $t0, $t1, 2 # $t1 should be 7 - ADD $t0, $t1, $t2 # $t2 should be 12 - MUL $t0, $t2 # LO should be 60 - CFLO $t3 # $t3 should be 60 - SUB $t1, $t0, $t4 # $t4 should be 2 - MUL $t3, $t4 # LO should be 120 - CFLO $t5 # $t5 should be 120 - DIV $t5, $t4 # HI should be 0, LO s.b. 60 - CFLO $t6 # $t6 should be 60 - CFHI $s7 # $s7 should be 0 - BEQ $0, $s7, 8 # write N if $s7 is not 0 - ADDI $0, $a0, 78 # 'N' - JAL outch - BLTZ $s7, 8 # write L if $s7 < 0 - ADDI $0, $a0, 76 # 'L' - JAL outch - BGTZ $s7, 8 # write H if $s7 < 0 - ADDI $0, $a0, 72 # 'H' - JAL outch - ADDI $0, $a0, 89 # 'Y' - JAL outch - EXIT - -outch: NOTR - PCH # arg already in $a0 - ADDI $0, $a0, 10 # \n - PCH - STRA -nl: NOTR - ADDI $0, $a0, 78 # $a0 is 78 ('N') - PCH - JR $ra - - .data 512 - WORD N = 78 - WORD L = 76 - WORD H = 72 - WORD nl = 10 - .stack 4096 - .end - diff --git a/vm/test.asm b/vm/test.asm deleted file mode 100755 index 82c70a9..0000000 --- a/vm/test.asm +++ /dev/null @@ -1,13 +0,0 @@ - .text 5 - PSTR $gp,0 - EXIT 1 - NOP - NOP - NOP - PSTR $gp,10 - EXIT 0 - .data 1024 - STRING[10] ERRMSG = "Should have started at location 5!\n" - STRING[10] GOOD = "OK, that started at the right spot!\n" - .stack 5024 - .end diff --git a/vm/test.c b/vm/test.c deleted file mode 100755 index f11b4b4..0000000 --- a/vm/test.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include "machine_types.h" -#include "instruction.h" - -#define MEMORY_SIZE_IN_WORDS 4096 -#define NUM_REGISTERS 8 - -// the VM's memory, both in word and binary instruction views. -static union mem_u { - word_type words[MEMORY_SIZE_IN_WORDS]; - uword_type uwords[MEMORY_SIZE_IN_WORDS]; - bin_instr_t instrs[MEMORY_SIZE_IN_WORDS]; -} memory; - -// general purpose registers -static word_type GPR[NUM_REGISTERS]; - -int main() -{ - printf("0xffff is %d\n", 0xffff); - GPR[0] = 0; - memory.words[GPR[0]] = 0xffff; - printf("memory.words[GPR[0]] is %d\n", memory.words[GPR[0]]); - fprintf(stdout, "%8d: %d\n", GPR[0], memory.words[GPR[0]]); - printf("zeroExt(0xff00) is %x in hex, %d in decimal\n", - machine_types_zeroExt(0xff00), - machine_types_zeroExt(0xff00)); - GPR[1] = 1; - immed_instr_t ii; - ii.immed = machine_types_zeroExt(0xff00); - printf("ii.immed is %x in hex, %d in decimal\n", ii.immed, ii.immed); - memory.words[GPR[1]] = 0 | ii.immed; - fprintf(stdout, "%8d: %d\n", GPR[1], memory.words[GPR[1]]); - memory.words[GPR[1]] = ii.immed | machine_types_zeroExt(0xff); - fprintf(stdout, "%8d: %d\n", GPR[1], memory.words[GPR[1]]); - - GPR[2] = 2; - uimmed_instr_t ui; - ui.uimmed = machine_types_zeroExt(0xff00); - printf("ui.uimmed is %x in hex, %d in decimal\n", ui.uimmed, ui.uimmed); - memory.uwords[GPR[2]] = 0 | ui.uimmed; - fprintf(stdout, "%8d: %d\n", GPR[2], memory.words[GPR[2]]); - memory.uwords[GPR[2]] = memory.uwords[GPR[2]] | machine_types_zeroExt(0xff); - fprintf(stdout, "%8d: %d\n", GPR[2], memory.uwords[GPR[2]]); - -} diff --git a/vm/test0.asm b/vm/test0.asm deleted file mode 100755 index caad989..0000000 --- a/vm/test0.asm +++ /dev/null @@ -1,6 +0,0 @@ -# $Id: test0.asm,v 1.2 2023/09/16 13:45:07 leavens Exp $ -.text start -start: EXIT -.data 12 -.stack 40 -.end diff --git a/vm/test_add.asm b/vm/test_add.asm deleted file mode 100755 index 32b1240..0000000 --- a/vm/test_add.asm +++ /dev/null @@ -1,9 +0,0 @@ - # $Id: test_add.asm,v 1.1 2023/09/22 01:29:49 leavens Exp $ - .text start -start: ADDI $0, $t7, 7 # put 7 in $t7 - ADDI $0, $t5, 5 # put 5 in $t5 - ADD $t5, $t7, $t2 # put 12 in $t2 - EXIT - .data 1024 - .stack 4096 - .end diff --git a/vm/token.c b/vm/token.c deleted file mode 100755 index 276654d..0000000 --- a/vm/token.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "token.h" - -#define NUM_TOKEN_TYPES 35 - -// Translation from enum values to strings -static const char *ttstrs[NUM_TOKEN_TYPES] = - {"identsym", "numbersym", "dottextsym", "dotdatasym", "dotendsym", - "colonsym", "equalsym", - "addopsym", "subopsym", "andopsym", "boropsym", "noropsym", "xoropsym", - "mulopsym", "divopsym", "sllopsym", "srlopsym", "mfhiopsym", "mfloopsym", - "jropsym", - "addiopsym", "andiopsym", "boriopsym", "xoriopsym", "noriopsym", - "beqopsym", "bgezopsym", "bgtzopsym", "bltzopsym", "bneopsym", - "lwopsym", "swopsym", "jmpaopsym", "callopsym", "rtnopsym" -}; - -// Requires: fname != NULL -// Create and return a fresh token with the given information -token token_make(token_type typ, const char *fname, - unsigned int line, unsigned int start_column, - const char *text, word_type value) { - token ret; - ret.typ = typ; - ret.filename = fname; - ret.line = line; - ret.start_column = start_column; - ret.text = text; - ret.value = value; - return ret; -} - - -// Return the name of the token_type enum -// corresponding to the given token_type value -const char *ttyp2str(token_type ttyp) -{ - return ttstrs[ttyp]; -} diff --git a/vm/token.h b/vm/token.h deleted file mode 100755 index ea88f45..0000000 --- a/vm/token.h +++ /dev/null @@ -1,39 +0,0 @@ -/* $Id: token.h,v 1.5 2024/07/17 19:55:30 leavens Exp $ */ -#ifndef _TOKEN_H -#define _TOKEN_H -#include "machine_types.h" - -#define MAX_IDENT_LENGTH 255 - -// types of tokens -typedef enum { - identsym, numbersym, dottextsym, dotdatasym, dotendsym, - colonsym, equalsym, - addopsym, subopsym, andopsym, boropsym, noropsym, xoropsym, - mulopsym, divopsym, sllopsym, srlopsym, mfhiopsym, mfloopsym, jropsym, - addiopsym, andiopsym, boriopsym, xoriopsym, noriopsym, - beqopsym, bgezopsym, bgtzopsym, bltzopsym, bneopsym, lwopsym, swopsym, - jmpaopsym, callopsym, rtnopsym -} token_type; - -// information about each token -typedef struct token { - token_type typ; - const char *filename; - unsigned int line; // the line the token occurs on - unsigned int start_column; // starting column for the token - const char *text; // the characters that make up the token's input - word_type value; // when typ==numbersym, its value -} token; - -// Requires: fname != NULL -// Create and return a fresh token with the given information -extern token token_make(token_type typ, const char *fname, - unsigned int line, unsigned int start_column, - const char *text, word_type value); - -// Return the name of the token_type enum -// corresponding to the given token_type value -extern const char *ttyp2str(token_type ttyp); - -#endif diff --git a/vm/type_distinction_demo.c b/vm/type_distinction_demo.c deleted file mode 100755 index d1ac50b..0000000 --- a/vm/type_distinction_demo.c +++ /dev/null @@ -1,50 +0,0 @@ -// $Id: type_distinction_demo.c,v 1.1 2024/07/28 13:02:44 leavens Exp $ -// This demonstration shows how one could leverage the C type checker -// to distinguish word and byte addresses. -// Unfortunately, one has to use structs for this, -// becuase C does structural type checking for all types except struct types -// yet it does by-name (nominal) type checking for struct types. -#include -#include -#include - -// in C, type checking will distinguish these types -typedef struct w_s { unsigned int w; } word_addr; -typedef struct b_s { unsigned int b; } byte_addr; - -// An example conversion factor -#define BYTES_PER_WORD 4 - -// Return the equivalent of the word address w as a byte address -byte_addr word2byte_address(word_addr w) -{ - byte_addr ret; - ret.b = BYTES_PER_WORD * w.w; - return ret; -} - -// Requires: b.b is a multiple of BYTES_PER_WORD. -// Return the equivalent of the byte address b as a word address -word_addr byte2word_address(byte_addr b) -{ - assert((b.b % BYTES_PER_WORD) == 0); - word_addr ret; - ret.w = b.b / BYTES_PER_WORD; - return ret; -} - -// A little demonstration -int main() -{ - word_addr worda; - byte_addr bytea; - worda.w = 1; - bytea = word2byte_address(worda); // okay, checked conversion - // bytea = worda; // type error! - worda.w += 1; - bytea = word2byte_address(worda); - bytea.b += 4; - worda = byte2word_address(bytea); - printf("worda: %d, bytea: %d\n", worda.w, bytea.b); - exit(0); -} diff --git a/vm/unparser_test1.asm b/vm/unparser_test1.asm deleted file mode 100755 index cdc0dab..0000000 --- a/vm/unparser_test1.asm +++ /dev/null @@ -1,12 +0,0 @@ - # $Id: unparser_test1.asm,v 1.3 2023/09/16 16:23:10 leavens Exp $ - .text go -go: ADD $8, $9, $10 - ADDI $0, $9, 52 - ADDI $0, $10, -0934 - EXIT - .data 0x1000 - WORD sixteen = 0x10 - WORD b25 = 25 - .stack 0x4000 - .end - diff --git a/vm/unparser_test2.asm b/vm/unparser_test2.asm deleted file mode 100755 index 72a7623..0000000 --- a/vm/unparser_test2.asm +++ /dev/null @@ -1,20 +0,0 @@ - # $Id: unparser_test2.asm,v 1.2 2023/09/16 13:29:58 leavens Exp $ - .text start -start: ADD $0, $1, $2 - SUB $3, $4, $5 - MUL $6, $7 - DIV $8, $9 - ADD $10, $11, $12 - ADD $13, $14, $15 - ADD $16, $17, $18 - SUB $19, $20, $21 - SUB $22, $23, $24 - MUL $25, $28 - ADD $29, $1, $8 - ADD $30, $1, $9 - JR $31 - EXIT - .data 1024 - .stack 4096 - .end - diff --git a/vm/utilities.c b/vm/utilities.c deleted file mode 100755 index e40eb93..0000000 --- a/vm/utilities.c +++ /dev/null @@ -1,94 +0,0 @@ -/* $Id: utilities.c,v 1.5 2024/07/23 14:25:45 leavens Exp $ */ -#include -#include -#include -#include -#include -#include -#include "utilities.h" - -// to turn off debugging support (assertions and debug_print) -// define the symbol NDEBUG (by writing uncommenting the following) -// #define NDEBUG - -#ifdef NDEBUG -#define debug_print() ((void)0) -#else -// otherwise debugging is on, and debug_print is defined as follows... -// (note that assert is a macro defined in -static void vdebug_print(const char *fmt, va_list args); - -// If debugging is false, do nothing, otherwise (when debugging) -// flush stderr and stdout, then print the message given on stderr, -// using printf formatting from the format string fmt. -// This function returns normally. -void debug_print(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - vdebug_print(fmt, args); - va_end(args); -} - -// The variadic version of debug_print -static void vdebug_print(const char *fmt, va_list args) -{ - // flush output streams to synchronize outputs - fflush(stdout); - fflush(stderr); - vfprintf(stderr, fmt, args); - fflush(stderr); -} -#endif - -static void vbail_with_error(const char* fmt, va_list args); - -// Format a string error message and print it followed by a newline on stderr -// using perror (for an OS error, if the errno is not 0) -// then exit with a failure code, so a call to this does not return. -void bail_with_error(const char *fmt, ...) -{ - fflush(stdout); // flush so output comes after what has happened already - va_list(args); - va_start(args, fmt); - vbail_with_error(fmt, args); -} - -// The variadic version of bail_with_error -static void vbail_with_error(const char* fmt, va_list args) -{ - extern int errno; - char buff[2048]; - vsprintf(buff, fmt, args); - if (errno != 0) { - perror(buff); - } else { - fprintf(stderr, "%s\n", buff); - } - fflush(stderr); - exit(EXIT_FAILURE); -} - -// Print an error message on stderr -// starting with the file name and line number from the floc argument -// (prints: filename, a colon, " line ", the line number, and a space) -// and then the message. -// Then exit with a failure code, so this function does not return. -void bail_with_prog_error(file_location floc, const char *fmt, ...) -{ - fflush(stdout); // flush so output comes after what has happened already - // print file, line, column information - fprintf(stderr, "%s: line %d ", floc.filename, floc.line); - - va_list(args); - va_start(args, fmt); - vbail_with_error(fmt, args); -} - - -// print a newline on out and flush out -void newline(FILE *out) -{ - fprintf(out, "\n"); - fflush(out); -} diff --git a/vm/utilities.h b/vm/utilities.h deleted file mode 100755 index 646e411..0000000 --- a/vm/utilities.h +++ /dev/null @@ -1,31 +0,0 @@ -/* $Id: utilities.h,v 1.6 2024/07/23 14:25:45 leavens Exp $ */ -#ifndef _UTILITIES_H -#define _UTILITIES_H -#include -#include -#include -#include "file_location.h" - -#define MAX(x,y) (((x)>(y))?(x):(y)) - -// If NDEBUG is defined, do nothing, otherwise (when debugging) -// flush stderr and stdout, then print the message given on stderr, -// using printf formatting from the format string fmt. -// This function returns normally. -void debug_print(const char *fmt, ...); - -// Format a string error message and print it using perror (for an OS error) -// then exit with a failure code, so a call to this does not return. -extern void bail_with_error(const char *fmt, ...); - -// Print an error message on stderr -// starting with the file name and line number from the floc argument -// (prints: filename, a colon, " line ", the line number, and a space) -// and then the message. -// Then exit with a failure code, so this function does not return. -extern void bail_with_prog_error(file_location floc, const char *fmt, ...); - -// print a newline on out and flush out -extern void newline(FILE *out); - -#endif diff --git a/vm/vm.c b/vm/vm.c deleted file mode 100755 index 9e2af74..0000000 --- a/vm/vm.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include "bof.h" -#include "utilities.h" -int main(int argc, char *argv[]) { - if (argc >= 2) { - BOFFILE bf = bof_read_open(argv[1]); - } else { - bail_with_error("Cannot read %s!", argv[1]); - } - return EXIT_SUCCESS; -} diff --git a/vm/vm_test0.asm b/vm/vm_test0.asm deleted file mode 100755 index 228752e..0000000 --- a/vm/vm_test0.asm +++ /dev/null @@ -1,9 +0,0 @@ - # $Id: vm_test0.asm,v 1.3 2024/07/26 12:44:46 leavens Exp $ - .text start -start: STRA - ADDI $sp, -1, 2 - EXIT 0 - .data 1024 - .stack 4096 - .end - diff --git a/vm/vm_test0.lst b/vm/vm_test0.lst deleted file mode 100755 index 2f5f311..0000000 --- a/vm/vm_test0.lst +++ /dev/null @@ -1,5 +0,0 @@ -Address Instruction - 0: STRA - 1: ADDI $sp, -1, 2 - 2: EXIT 0 - 1024: 0 ... diff --git a/vm/vm_test1.asm b/vm/vm_test1.asm deleted file mode 100755 index a1b026f..0000000 --- a/vm/vm_test1.asm +++ /dev/null @@ -1,22 +0,0 @@ - # $Id: vm_test1.asm,v 1.6 2024/07/29 02:01:32 leavens Exp $ - .text start -start: STRA - SRI $sp, 2 # allocate 2 words on the stack - ADDI $sp, 1, 1 # put 1 in memory[$sp+1] - ADD $gp, 2, $sp, 1 # put 1 in temp - ADD $sp, 0, $gp, 2 # put 1 in stack top - SUB $gp, 2, $gp, 2 # zero out temp - ADDI $sp, 0, 10 # add 10 to stack top, should be 11 - SRI $sp, 1 # allocate a word on the stack - NOTR - PCH $gp, 0 # print y - PCH $gp, 3 # print nl - EXIT 0 - .data 1024 - CHAR y = 'y' - CHAR n = 'n' - WORD temp # not initialized - CHAR nl = '\n' - .stack 4096 - .end - diff --git a/vm/vm_test1.lst b/vm/vm_test1.lst deleted file mode 100755 index 21811d8..0000000 --- a/vm/vm_test1.lst +++ /dev/null @@ -1,15 +0,0 @@ -Address Instruction - 0: STRA - 1: SRI $sp, 2 - 2: ADDI $sp, 1, 1 - 3: ADD $gp, 2, $sp, 1 - 4: ADD $sp, 0, $gp, 2 - 5: SUB $gp, 2, $gp, 2 - 6: ADDI $sp, 0, 10 - 7: SRI $sp, 1 - 8: NOTR - 9: PCH $gp, 0 - 10: PCH $gp, 3 - 11: EXIT 0 - 1024: 121 1025: 110 1026: 0 1027: 10 1028: 0 - ... diff --git a/vm/vm_test2.asm b/vm/vm_test2.asm deleted file mode 100755 index ae29738..0000000 --- a/vm/vm_test2.asm +++ /dev/null @@ -1,19 +0,0 @@ - # $Id: vm_test2.asm,v 1.3 2024/07/29 02:01:32 leavens Exp $ - .text start -start: ADDI $sp, 0, 1 # top of stack is 1 - ADD $sp, 0, $sp, 0 # top of stack is 2 - ADDI $sp, 0, 1 # top of stack is 3 - ADD $sp, 0, $sp, 0 # $top of stack is 6 - SLL $sp, 0, 1 # top of stack is 12 - SRI $sp, 4 # allocate a word on the stack - # NOTR - PCH $gp, 1 # print 'Y' - PCH $gp, 2 # print '\n' - EXIT 0 - .data 1024 - WORD x = 33 - CHAR y = 'Y' - CHAR nl = '\n' - .stack 4096 - .end - diff --git a/vm/vm_test2.lst b/vm/vm_test2.lst deleted file mode 100755 index 5c98036..0000000 --- a/vm/vm_test2.lst +++ /dev/null @@ -1,12 +0,0 @@ -Address Instruction - 0: ADDI $sp, 0, 1 - 1: ADD $sp, 0, $sp, 0 - 2: ADDI $sp, 0, 1 - 3: ADD $sp, 0, $sp, 0 - 4: SLL $sp, 0, 1 - 5: SRI $sp, 4 - 6: PCH $gp, 1 - 7: PCH $gp, 2 - 8: EXIT 0 - 1024: 33 1025: 89 1026: 10 1027: 0 ... - diff --git a/vm/vm_test3.asm b/vm/vm_test3.asm deleted file mode 100755 index cbc4354..0000000 --- a/vm/vm_test3.asm +++ /dev/null @@ -1,30 +0,0 @@ - # $Id: vm_test3.asm,v 1.5 2024/08/29 20:26:00 leavens Exp $ - .text start -start: STRA - ADDI $sp, 0, 30 # stack top is 30 - SRI $sp, 1 # subtract 1 from SP (allocate a word) - ADDI $sp, 0, 20 # top of stack is 20 - ADDI $sp, 0, 10 # stack top is 30 - BNE $sp, 1, +3 # skip if stack top and stack+1 are not equal - CALL yes - JMPA done - CALL no - JMPA done -yes: NOTR - PSTR $gp, 1 # print yes - RTN -no: NOTR - PSTR $gp, 2 # print no - RTN - STRA - EXIT 1 -done: STRA - EXIT 0 - - .data 1024 - WORD x = 33 - STRING[1] yeah = "Y\n" - STRING[1] nay = "No\n" - .stack 4096 - .end - diff --git a/vm/vm_test3.lst b/vm/vm_test3.lst deleted file mode 100755 index 30d709b..0000000 --- a/vm/vm_test3.lst +++ /dev/null @@ -1,23 +0,0 @@ -Address Instruction - 0: STRA - 1: ADDI $sp, 0, 30 - 2: SRI $sp, 1 - 3: ADDI $sp, 0, 20 - 4: ADDI $sp, 0, 10 - 5: BNE $sp, 1, 3 # target is word address 8 - 6: CALL 10 # target is word address 10 - 7: JMPA 18 # target is word address 18 - 8: CALL 13 # target is word address 13 - 9: JMPA 18 # target is word address 18 - 10: NOTR - 11: PSTR $gp, 1 - 12: RTN - 13: NOTR - 14: PSTR $gp, 2 - 15: RTN - 16: STRA - 17: EXIT 1 - 18: STRA - 19: EXIT 0 - 1024: 33 1025: 2649 1026: 683854 1027: 0 ... - diff --git a/vm/vm_test4.asm b/vm/vm_test4.asm deleted file mode 100755 index f8e1437..0000000 --- a/vm/vm_test4.asm +++ /dev/null @@ -1,51 +0,0 @@ -# $Id: vm_test4.asm,v 1.5 2024/08/29 20:26:00 leavens Exp $ - .text start -start: NOTR - STRA - ADDI $sp, 0, 5 # stack top is 5 - ADDI $sp, -1, 2 # memory[SP-1] is 2 - ARI $sp, -1 # make stack top point to where the 2 is - ADD $sp, 0, $sp, 1 # stack top should be 7 - MUL $sp, 1 # LO should be (5 * 7) = 35 - SRI $sp, 1 # allocate a word on stack - CFLO $sp, 0 # stack top is 35 - SUB $sp, 0, $sp, 1 # stack top should be (35-7) = 28 - MUL $sp, 2 # LO should be (28 * 5) = 140 - SRI $sp, 1 # allocate a word on stack - CFLO $sp, 0 # stack top is 140 - SRI $sp, 1 # allocate a word on stack - CPW $sp, 0, $sp, 2 # put 28 on top of stack - DIV $sp, 4 # HI should be (28 % 5) = 3, LO s.b. (28 / 5) = 5 - SRI $sp, 2 # allocate two words on stack - CFLO $sp, 0 # stack top should be 5 - CFHI $sp, 1 # second from top should be 3 - SRI $sp, 1 # allocate a word on the stack - ADDI $sp, 0, 5 # store 5! on top of stack - BEQ $sp, 1, 2 # write no and exit 1 if memory[$sp+1] is not 5 - CALL no - CALL yes - ARI $sp, 1 # pop a word off the stack - SWR $sp, 0, $r4 # store a 0 (from $r4) into top of stack - ADDI $sp, 0, 3 # make top of stack be 3 - BEQ $sp, 1, 2 # write no if memory[$sp+1] is not 3 - CALL no - CALL yes -done: EXIT 0 - -yes: NOTR - PSTR $gp, 0 # print "y\n" - STRA - RTN - -no: NOTR - PSTR $gp, 1 # print "no\n" - STRA - EXIT 1 - RTN - - .data 512 - STRING[1] y = "y\n" - STRING[1] n = "no\n" - .stack 4096 - .end - diff --git a/vm/vm_test4.lst b/vm/vm_test4.lst deleted file mode 100755 index 48c4f84..0000000 --- a/vm/vm_test4.lst +++ /dev/null @@ -1,43 +0,0 @@ -Address Instruction - 0: NOTR - 1: STRA - 2: ADDI $sp, 0, 5 - 3: ADDI $sp, -1, 2 - 4: ARI $sp, -1 - 5: ADD $sp, 0, $sp, 1 - 6: MUL $sp, 1 - 7: SRI $sp, 1 - 8: CFLO $sp, 0 - 9: SUB $sp, 0, $sp, 1 - 10: MUL $sp, 2 - 11: SRI $sp, 1 - 12: CFLO $sp, 0 - 13: SRI $sp, 1 - 14: CPW $sp, 0, $sp, 2 - 15: DIV $sp, 4 - 16: SRI $sp, 2 - 17: CFLO $sp, 0 - 18: CFHI $sp, 1 - 19: SRI $sp, 1 - 20: ADDI $sp, 0, 5 - 21: BEQ $sp, 1, 2 # target is word address 23 - 22: CALL 35 # target is word address 35 - 23: CALL 31 # target is word address 31 - 24: ARI $sp, 1 - 25: SWR $sp, 0, $r4 - 26: ADDI $sp, 0, 3 - 27: BEQ $sp, 1, 2 # target is word address 29 - 28: CALL 35 # target is word address 35 - 29: CALL 31 # target is word address 31 - 30: EXIT 0 - 31: NOTR - 32: PSTR $gp, 0 - 33: STRA - 34: RTN - 35: NOTR - 36: PSTR $gp, 1 - 37: STRA - 38: EXIT 1 - 39: RTN - 512: 2681 513: 683886 514: 0 ... - diff --git a/vm/vm_test5.asm b/vm/vm_test5.asm deleted file mode 100755 index 6b4fa20..0000000 --- a/vm/vm_test5.asm +++ /dev/null @@ -1,49 +0,0 @@ - # $Id: vm_test5.asm,v 1.4 2024/08/29 20:26:00 leavens Exp $ - .text start -start: ADDI $sp, 0, 0x7 # stack top is 7 - ADDI $sp, -1, 0xf # 1 above stack top is 15 - ARI $sp, -1 # make the stack top be the location with 15 - LWR $r4, $gp, 0 # $r4 should be 2 - AND $sp, 0, $sp, 0 # stack top should (still) be 15 - SLL $sp, 0, 5 # stack top should be 480 - ADDI $sp, 0, -405 # stack top is 75 - SRI $sp, 1 # allocate a word on the stack - ADDI $sp, 0, 2 # put 2 on top of stack - SLL $sp, 0, 7 # top of stack is 256 - SRL $sp, 0, 2 # stack top is 64 - ARI $sp, -1 # allocate a word on the stack - LIT $sp, 0, 11 # put 11 on top of stack - LWR $r5, $sp, 0 # put 11 in $r5 - XOR $sp, 0, $sp, 0 # make top of stack be 0 - SWR $sp, 0, $r5 # put 11 on top of stack - NEG $sp, 0, $sp, 0 # make top of stack be -11 - LIT $sp, 1, 75 # put 75 in memory[SP+1] - ARI $sp, 1 # pop the stack - BNE $sp, 1, 3 # skip if top 2 stack elements are not equal - CALL y - JMPA done - CALL n - JMPA bad -done: EXIT 0 -bad: EXIT 1 - -y: NOTR - PSTR $gp, 5 - STRA - RTN - -n: NOTR - PSTR $gp, 1 - STRA - RTN - - .data 512 - WORD TWO = 2 - STRING[1] No = "No\n" - WORD L = 76 - WORD H = 72 - WORD nl = 10 - STRING[2] Yes = "Yes!\n" - .stack 4096 - .end - diff --git a/vm/vm_test5.lst b/vm/vm_test5.lst deleted file mode 100755 index 1e1032e..0000000 --- a/vm/vm_test5.lst +++ /dev/null @@ -1,38 +0,0 @@ -Address Instruction - 0: ADDI $sp, 0, 7 - 1: ADDI $sp, -1, 15 - 2: ARI $sp, -1 - 3: LWR $r4, $gp, 0 - 4: AND $sp, 0, $sp, 0 - 5: SLL $sp, 0, 5 - 6: ADDI $sp, 0, -405 - 7: SRI $sp, 1 - 8: ADDI $sp, 0, 2 - 9: SLL $sp, 0, 7 - 10: SRL $sp, 0, 2 - 11: ARI $sp, -1 - 12: LIT $sp, 0, 11 - 13: LWR $r5, $sp, 0 - 14: XOR $sp, 0, $sp, 0 - 15: SWR $sp, 0, $r5 - 16: NEG $sp, 0, $sp, 0 - 17: LIT $sp, 1, 75 - 18: ARI $sp, 1 - 19: BNE $sp, 1, 3 # target is word address 22 - 20: CALL 26 # target is word address 26 - 21: JMPA 24 # target is word address 24 - 22: CALL 30 # target is word address 30 - 23: JMPA 25 # target is word address 25 - 24: EXIT 0 - 25: EXIT 1 - 26: NOTR - 27: PSTR $gp, 5 - 28: STRA - 29: RTN - 30: NOTR - 31: PSTR $gp, 1 - 32: STRA - 33: RTN - 512: 2 513: 683854 514: 76 515: 72 516: 10 - 517: 561210713 518: 10 519: 0 ... - diff --git a/vm/vm_test6.asm b/vm/vm_test6.asm deleted file mode 100755 index 2885829..0000000 --- a/vm/vm_test6.asm +++ /dev/null @@ -1,32 +0,0 @@ - # $Id: vm_test6.asm,v 1.7 2024/08/29 20:26:00 leavens Exp $ - .text start -start: ADDI $sp, -1, 1 # one word above top of stack gets 1 - CPW $sp, 0, $sp, -1 - SLL $sp, -1, 20 # one word above top of stack gets 2^20 - SRI $sp, 1 # SP = SP - 1 - ADD $sp, 0, $gp, 0 # top of stack is 2^20+1 - SRI $sp, 1 # allocate a word - LIT $sp, 0, 4 # put 4 on top of stack - LWR $r4, $sp, 0 # $r4 is 4 - LIT $sp, 0, 14 # top of stack is 14 - LWR $r5, $sp, 0 # $r5 is 14 - SWR $sp, -1, $r4 # one word above top of stack gets 4 - ARI $sp, -2 # allocate 2 words on the stack - SWR $sp, 0, $r5 # top of stack gets 14 - DIV $sp, 1 # HI is 2, LO is 3 - CFLO $gp, 2 # dividend holds 3 - CFHI $gp, 1 # rem is 2 - SRI $sp, 1 # allocate a word on top of stack - LIT $sp, 0, 1 # top of stack gets 1 - SLL $sp, 0, 10 # put 2^10 (i.e., 1024) on top of stack - MUL $sp, 0 # square top of stack, result in (HI, LO) - CFHI $sp, -2 - CFLO $sp, -1 - SRI $sp, 2 - EXIT 0 - .data 1024 - WORD one = 1 - WORD rem = 0 - WORD dividend = 0 - .stack 4096 - .end diff --git a/vm/vm_test6.lst b/vm/vm_test6.lst deleted file mode 100755 index bf109ae..0000000 --- a/vm/vm_test6.lst +++ /dev/null @@ -1,26 +0,0 @@ -Address Instruction - 0: ADDI $sp, -1, 1 - 1: CPW $sp, 0, $sp, -1 - 2: SLL $sp, -1, 20 - 3: SRI $sp, 1 - 4: ADD $sp, 0, $gp, 0 - 5: SRI $sp, 1 - 6: LIT $sp, 0, 4 - 7: LWR $r4, $sp, 0 - 8: LIT $sp, 0, 14 - 9: LWR $r5, $sp, 0 - 10: SWR $sp, -1, $r4 - 11: ARI $sp, -2 - 12: SWR $sp, 0, $r5 - 13: DIV $sp, 1 - 14: CFLO $gp, 2 - 15: CFHI $gp, 1 - 16: SRI $sp, 1 - 17: LIT $sp, 0, 1 - 18: SLL $sp, 0, 10 - 19: MUL $sp, 0 - 20: CFHI $sp, -2 - 21: CFLO $sp, -1 - 22: SRI $sp, 2 - 23: EXIT 0 - 1024: 1 1025: 0 ... diff --git a/vm/vm_test7.asm b/vm/vm_test7.asm deleted file mode 100755 index 4c56b98..0000000 --- a/vm/vm_test7.asm +++ /dev/null @@ -1,63 +0,0 @@ - # $Id: vm_test7.asm,v 1.5 2024/08/15 18:39:21 leavens Exp $ - # manipulation of the runtime stack - .text main -main: SRI $sp, 6 # put numbers in the registers - LIT $sp, 6, 7 - LWR $ra, $sp, 6 - LIT $sp, 5, 6 - LWR $r6, $sp, 5 - LIT $sp, 4, 5 - LWR $r5, $sp, 4 - LIT $sp, 3, 4 - LWR $r4, $sp, 3 - LIT $sp, 2, 3 - LWR $r3, $sp, 2 - LIT $sp, 1, 2 - # LWR $sp, $sp, 1 # putting 2 in $sp would violate a machine invariant - SCA $sp, 0, $sp, 0 - - CALL callerSave - SRI $sp, 1 - LIT $sp, 0, -1 - LWR $r6, $sp, 0 - LWR $r5, $sp, 0 - LWR $r4, $sp, 0 - LWR $r3, $sp, 0 - ARI $sp, 1 - CALL callerRestore - - EXIT 0 -bad: EXIT 1 - - # callerSave is a subroutine that saves the registers - # that a caller might need to save on the stack. - # These registers are left undistubed... - # However, since this is a subroutine, it can't save $ra, - # and it disturbs $sp, so those would need to be saved first -callerSave: SRI $sp, 5 # allocate 5 words on the stack - SWR $sp, 4, $fp # save $fp... - SWR $sp, 3, $r3 - SWR $sp, 2, $r4 - SWR $sp, 1, $r5 - SWR $sp, 0, $r6 - RTN - - - # callerRestore is a subroutine that restores all registers - # that were saved by callerSave (on the stack) - # Assuming the runtime stack is in the same state it was - # after calling callerSave, it also restores the $sp - # to its previous value. - # Note that the user will need to restore $ra manually - # after calling this subroutine. -callerRestore: LWR $r6, $sp, 0 - LWR $r5, $sp, 1 # restore $r5 ... - LWR $r4, $sp, 2 - LWR $r3, $sp, 3 - LWR $fp, $sp, 4 - ARI $sp, 5 # deallocate the 5 words - RTN - - .data 1024 - .stack 4096 - .end diff --git a/vm/vm_test7.lst b/vm/vm_test7.lst deleted file mode 100755 index 6f183f6..0000000 --- a/vm/vm_test7.lst +++ /dev/null @@ -1,40 +0,0 @@ -Address Instruction - 0: SRI $sp, 6 - 1: LIT $sp, 6, 7 - 2: LWR $ra, $sp, 6 - 3: LIT $sp, 5, 6 - 4: LWR $r6, $sp, 5 - 5: LIT $sp, 4, 5 - 6: LWR $r5, $sp, 4 - 7: LIT $sp, 3, 4 - 8: LWR $r4, $sp, 3 - 9: LIT $sp, 2, 3 - 10: LWR $r3, $sp, 2 - 11: LIT $sp, 1, 2 - 12: SCA $sp, 0, $sp, 0 - 13: CALL 24 # target is word address 24 - 14: SRI $sp, 1 - 15: LIT $sp, 0, -1 - 16: LWR $r6, $sp, 0 - 17: LWR $r5, $sp, 0 - 18: LWR $r4, $sp, 0 - 19: LWR $r3, $sp, 0 - 20: ARI $sp, 1 - 21: CALL 31 # target is word address 31 - 22: EXIT 0 - 23: EXIT 1 - 24: SRI $sp, 5 - 25: SWR $sp, 4, $fp - 26: SWR $sp, 3, $r3 - 27: SWR $sp, 2, $r4 - 28: SWR $sp, 1, $r5 - 29: SWR $sp, 0, $r6 - 30: RTN - 31: LWR $r6, $sp, 0 - 32: LWR $r5, $sp, 1 - 33: LWR $r4, $sp, 2 - 34: LWR $r3, $sp, 3 - 35: LWR $fp, $sp, 4 - 36: ARI $sp, 5 - 37: RTN - 1024: 0 ... diff --git a/vm/vm_test8.asm b/vm/vm_test8.asm deleted file mode 100755 index 936dd30..0000000 --- a/vm/vm_test8.asm +++ /dev/null @@ -1,14 +0,0 @@ - # $Id: vm_test8.asm,v 1.4 2024/08/15 18:58:50 leavens Exp $ - .text 0 - LIT $sp, 0, 17 - LWR $r4, $sp, 0 # put 14 in $r4 - SRI $sp, 2 - LIT $sp, 0, 19 - LWR $r5, $sp, 0 # put 19 in $r5 - SCA $sp, -1, $sp, 0 # store stack top address - LWI $sp, -2, $sp, -1 - SRI $sp, 2 - EXIT 0 - .data 256 - .stack 1024 - .end diff --git a/vm/vm_test8.lst b/vm/vm_test8.lst deleted file mode 100755 index 7baf6da..0000000 --- a/vm/vm_test8.lst +++ /dev/null @@ -1,11 +0,0 @@ -Address Instruction - 0: LIT $sp, 0, 17 - 1: LWR $r4, $sp, 0 - 2: SRI $sp, 2 - 3: LIT $sp, 0, 19 - 4: LWR $r5, $sp, 0 - 5: SCA $sp, -1, $sp, 0 - 6: LWI $sp, -2, $sp, -1 - 7: SRI $sp, 2 - 8: EXIT 0 - 256: 0 ... diff --git a/vm/vm_test9.asm b/vm/vm_test9.asm deleted file mode 100755 index bf5c48d..0000000 --- a/vm/vm_test9.asm +++ /dev/null @@ -1,24 +0,0 @@ - # $Id: vm_test9.asm,v 1.2 2024/08/22 03:03:33 leavens Exp $ - .text 0 - SRI $sp, 1 - XORI $sp, 0, 0x567a - LIT $sp, -1, 0x67a - BORI $sp, -1, 0x5000 - BNE $sp, -1, 8 # fail if not equal - ANDI $sp, 0, 0xFFF - LIT $sp, -2, 0x67a - BNE $sp, -2, 5 # fail if not equal -good: NOTR - PSTR $gp, 0 - STRA - EXIT 0 -bad: NOTR - PSTR $gp, 1 - STRA - EXIT 1 - .data 1024 - STRING[1] Y = "Y\n" - STRING [1] no = "no\n" - CHAR nl = '\n' - .stack 4096 - .end diff --git a/vm/vm_test9.lst b/vm/vm_test9.lst deleted file mode 100755 index a29cd61..0000000 --- a/vm/vm_test9.lst +++ /dev/null @@ -1,19 +0,0 @@ -Address Instruction - 0: SRI $sp, 1 - 1: XORI $sp, 0, 0x567a - 2: LIT $sp, -1, 1658 - 3: BORI $sp, -1, 0x5000 - 4: BNE $sp, -1, 8 # target is word address 12 - 5: ANDI $sp, 0, 0xfff - 6: LIT $sp, -2, 1658 - 7: BNE $sp, -2, 5 # target is word address 12 - 8: NOTR - 9: PSTR $gp, 0 - 10: STRA - 11: EXIT 0 - 12: NOTR - 13: PSTR $gp, 1 - 14: STRA - 15: EXIT 1 - 1024: 2649 1025: 683886 1026: 10 1027: 0 ... - diff --git a/vm/vm_testA.asm b/vm/vm_testA.asm deleted file mode 100755 index ec25988..0000000 --- a/vm/vm_testA.asm +++ /dev/null @@ -1,21 +0,0 @@ - # $Id: vm_testA.asm,v 1.1 2024/08/22 13:33:49 leavens Exp $ - .text 0 - SRI $sp, 1 - XORI $sp, 0, 0xffff - LIT $sp, -1, 0xff - BORI $sp, -1, 0xff00 - BNE $sp, -1, 5 # fail if not equal -good: NOTR - PSTR $gp, 0 - STRA - EXIT 0 -bad: NOTR - PSTR $gp, 1 - STRA - EXIT 1 - .data 1024 - STRING[1] Y = "Y\n" - STRING [1] no = "no\n" - CHAR nl = '\n' - .stack 4096 - .end diff --git a/vm/vm_testA.lst b/vm/vm_testA.lst deleted file mode 100755 index 138e707..0000000 --- a/vm/vm_testA.lst +++ /dev/null @@ -1,16 +0,0 @@ -Address Instruction - 0: SRI $sp, 1 - 1: XORI $sp, 0, 0xffff - 2: LIT $sp, -1, 255 - 3: BORI $sp, -1, 0xff00 - 4: BNE $sp, -1, 5 # target is word address 9 - 5: NOTR - 6: PSTR $gp, 0 - 7: STRA - 8: EXIT 0 - 9: NOTR - 10: PSTR $gp, 1 - 11: STRA - 12: EXIT 1 - 1024: 2649 1025: 683886 1026: 10 1027: 0 ... - diff --git a/vm/vm_testB.asm b/vm/vm_testB.asm deleted file mode 100755 index 856db8f..0000000 --- a/vm/vm_testB.asm +++ /dev/null @@ -1,22 +0,0 @@ - # $Id: vm_testB.asm,v 1.1 2024/08/22 14:29:52 leavens Exp $ - .text 0 - SRI $sp, 1 - XORI $sp, 0, 0xffff - LIT $sp, -1, 0xff - LIT $sp, -2, -1 - BORI $sp, -1, 0xff00 - BNE $sp, -1, 5 # fail if not equal -good: NOTR - PSTR $gp, 0 - STRA - EXIT 0 -bad: NOTR - PSTR $gp, 1 - STRA - EXIT 1 - .data 1024 - STRING[1] Y = "Y\n" - STRING [1] no = "no\n" - CHAR nl = '\n' - .stack 4096 - .end diff --git a/vm/vm_testB.lst b/vm/vm_testB.lst deleted file mode 100755 index acfa67b..0000000 --- a/vm/vm_testB.lst +++ /dev/null @@ -1,17 +0,0 @@ -Address Instruction - 0: SRI $sp, 1 - 1: XORI $sp, 0, 0xffff - 2: LIT $sp, -1, 255 - 3: LIT $sp, -2, -1 - 4: BORI $sp, -1, 0xff00 - 5: BNE $sp, -1, 5 # target is word address 10 - 6: NOTR - 7: PSTR $gp, 0 - 8: STRA - 9: EXIT 0 - 10: NOTR - 11: PSTR $gp, 1 - 12: STRA - 13: EXIT 1 - 1024: 2649 1025: 683886 1026: 10 1027: 0 ... - diff --git a/vm/vm_testC.asm b/vm/vm_testC.asm deleted file mode 100755 index bae0e32..0000000 --- a/vm/vm_testC.asm +++ /dev/null @@ -1,29 +0,0 @@ - # $Id: vm_testC.asm,v 1.1 2024/09/25 14:16:06 leavens Exp $ - .text 0 - SRI $sp, 1 # allocate a word on stack - LIT $sp, 0, 1 # put a 1 on top of the stack - SLL $sp, 0, 30 # make top of stack be 2^30 - SUB $sp, 0, $gp, 0 # make top of stack be (2^30)-1 - BEQ $gp, 7, +2 - JMPA wrong - MUL $sp, 0 # (HI,LO) is ((2^30)-1)^2 - CFHI $sp, 0 # HI is most significant bits of result - BEQ $gp, 8, +2 - JMPA wrong - CFLO $sp, 0 - BEQ $gp, 9, +2 - JMPA wrong - NOTR -pass: PSTR $gp, 4 - EXIT 0 -wrong: PSTR $gp, 1 - EXIT 1 - .data 4096 - WORD one = 1 - STRING[3] Wrong = "Wrong!\n" - STRING[3] Passed = "Passed!\n" - WORD two30m1 = 1073741823 # (2^30)-1 - WORD mostSignif = 268435455 - WORD leastSignif = -2147483647 - .stack 32000 - .end diff --git a/vm/vm_testC.lst b/vm/vm_testC.lst deleted file mode 100755 index 9a912c3..0000000 --- a/vm/vm_testC.lst +++ /dev/null @@ -1,23 +0,0 @@ -Address Instruction - 0: SRI $sp, 1 - 1: LIT $sp, 0, 1 - 2: SLL $sp, 0, 30 - 3: SUB $sp, 0, $gp, 0 - 4: BEQ $gp, 7, 2 # target is word address 6 - 5: JMPA 16 # target is word address 16 - 6: MUL $sp, 0 - 7: CFHI $sp, 0 - 8: BEQ $gp, 8, 2 # target is word address 10 - 9: JMPA 16 # target is word address 16 - 10: CFLO $sp, 0 - 11: BEQ $gp, 9, 2 # target is word address 13 - 12: JMPA 16 # target is word address 16 - 13: NOTR - 14: PSTR $gp, 4 - 15: EXIT 0 - 16: PSTR $gp, 1 - 17: EXIT 1 - 4096: 1 4097: 1852797527 4098: 663911 4099: 0 - 4100: 1936941392 4101: 169960549 4102: 0 4103: 1073741823 - 4104: 268435455 4105: -2147483647 4106: 0 ... - diff --git a/vm/vm_testD.asm b/vm/vm_testD.asm deleted file mode 100755 index 35210df..0000000 --- a/vm/vm_testD.asm +++ /dev/null @@ -1,37 +0,0 @@ - # $Id: vm_testD.asm,v 1.1 2024/09/25 19:46:40 leavens Exp $ - .text 0 - SRI $sp, 2 # allocate 2 words on stack - LIT $sp, 0, 1 # put a 1 on top of the stack - LIT $sp, 1, 1 # put a 1 just above the top of stack - PINT $sp, 1 - BEQ $sp, 1, +2 - JMPA wrong - SLL $sp, 0, 30 # make top of stack be 2^30 - SUB $sp, 0, $gp, 0 # make top of stack be (2^30)-1 - CPW $sp, 1, $sp, 0 # make ($sp+1) be (2^30)-1 - PINT $sp, 0 - PINT $gp, 7 - CPW $sp, 0, $sp, 1 # restore top of stack - BEQ $gp, 7, +2 - JMPA wrong - MUL $sp, 0 # (HI,LO) is ((2^30)-1)^2 - CFHI $sp, 0 # HI is most significant bits of result - BEQ $gp, 8, +2 - JMPA wrong - CFLO $sp, 0 - BEQ $gp, 9, +2 - JMPA wrong - NOTR -pass: PSTR $gp, 4 - EXIT 0 -wrong: PSTR $gp, 1 - EXIT 1 - .data 4096 - WORD one = 1 - STRING[3] Wrong = "Wrong!\n" - STRING[3] Passed = "Passed!\n" - WORD two30m1 = 1073741823 # (2^30)-1 - WORD mostSignif = 268435455 - WORD leastSignif = -2147483647 - .stack 32000 - .end diff --git a/vm/vm_testD.lst b/vm/vm_testD.lst deleted file mode 100755 index 835f89d..0000000 --- a/vm/vm_testD.lst +++ /dev/null @@ -1,31 +0,0 @@ -Address Instruction - 0: SRI $sp, 2 - 1: LIT $sp, 0, 1 - 2: LIT $sp, 1, 1 - 3: PINT $sp, 1 - 4: BEQ $sp, 1, 2 # target is word address 6 - 5: JMPA 24 # target is word address 24 - 6: SLL $sp, 0, 30 - 7: SUB $sp, 0, $gp, 0 - 8: CPW $sp, 1, $sp, 0 - 9: PINT $sp, 0 - 10: PINT $gp, 7 - 11: CPW $sp, 0, $sp, 1 - 12: BEQ $gp, 7, 2 # target is word address 14 - 13: JMPA 24 # target is word address 24 - 14: MUL $sp, 0 - 15: CFHI $sp, 0 - 16: BEQ $gp, 8, 2 # target is word address 18 - 17: JMPA 24 # target is word address 24 - 18: CFLO $sp, 0 - 19: BEQ $gp, 9, 2 # target is word address 21 - 20: JMPA 24 # target is word address 24 - 21: NOTR - 22: PSTR $gp, 4 - 23: EXIT 0 - 24: PSTR $gp, 1 - 25: EXIT 1 - 4096: 1 4097: 1852797527 4098: 663911 4099: 0 - 4100: 1936941392 4101: 169960549 4102: 0 4103: 1073741823 - 4104: 268435455 4105: -2147483647 4106: 0 ... - diff --git a/vm/vm_testE.asm b/vm/vm_testE.asm deleted file mode 100755 index 9f79085..0000000 --- a/vm/vm_testE.asm +++ /dev/null @@ -1,12 +0,0 @@ - # $Id: vm_testE.asm,v 1.1 2024/11/10 14:34:25 leavens Exp leavens $ - .text 0 - SRI $sp, 1 - CPR $sp, $fp - SWR $sp, 0, $sp - SWR $gp, 0, $fp - BEQ $gp, 0, 2 -bad: EXIT 1 -okay: EXIT 0 - .data 2048 - .stack 8096 - .end diff --git a/vm/vm_testE.lst b/vm/vm_testE.lst deleted file mode 100755 index 2a7a7ca..0000000 --- a/vm/vm_testE.lst +++ /dev/null @@ -1,9 +0,0 @@ -Address Instruction - 0: SRI $sp, 1 - 1: CPR $sp, $fp - 2: SWR $sp, 0, $sp - 3: SWR $gp, 0, $fp - 4: BEQ $gp, 0, 2 # target is word address 6 - 5: EXIT 1 - 6: EXIT 0 - 2048: 0 ...