From 54ff265d0ac8c8b3869095fdcb8672a0ce3d5d90 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Tue, 21 Oct 2014 12:31:47 -0400 Subject: [PATCH] Tweaked function call, string, and character code generation --- source/sclpl/codegen.c | 46 +++++++++++++++++++++++++++++++++++++----- source/sclpl/lexer.c | 3 ++- source/sclpl/main.c | 5 ++--- source/sclpl/pprint.c | 2 +- spec/codegen_spec.rb | 19 ++++++++++++++++- 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/source/sclpl/codegen.c b/source/sclpl/codegen.c index 8bc9324..a3ca7e8 100644 --- a/source/sclpl/codegen.c +++ b/source/sclpl/codegen.c @@ -84,6 +84,34 @@ static void print_indent(int depth) { printf("%c", ' '); } +static void print_char(char ch) { + switch (ch) { + case '\r': printf("__char('\\r')"); break; + case '\n': printf("__char('\\n')"); break; + case '\t': printf("__char('\\t')"); break; + case '\v': printf("__char('\\v')"); break; + default: printf("__char('%c')", ch); break; + } +} + +static void print_string(const char* str) { + printf("__string(\""); + while('\0' != str[0]) + { + switch (str[0]) { + case '\r': printf("\\r"); break; + case '\n': printf("\\n"); break; + case '\t': printf("\\t"); break; + case '\v': printf("\\v"); break; + default: printf("%c", str[0]); break; + } + str++; + } + printf("\")"); +} + +/*****************************************************************************/ + static void emit_header(void) { puts("#include \n"); } @@ -113,8 +141,8 @@ static void emit_expression(vec_t* fnlst, tree_t* p_tree, int depth) { if (p_tree->tag == ATOM) { lex_tok_t* tok = p_tree->ptr.tok; switch (tok->type) { - case T_STRING: printf("__string(%s)", ((char*)tok->value)); break; - case T_CHAR: printf("__char('%c')", ((char)(int)tok->value)); break; + case T_STRING: print_string(((char*)tok->value)); break; + case T_CHAR: print_char(((char)(int)tok->value)); break; case T_INT: printf("__int(%ld)", *((long int*)tok->value)); break; case T_FLOAT: printf("__float(%f)", *((double*)tok->value)); break; case T_BOOL: printf("__bool(%s)", ((int)tok->value)?"true":"false"); break; @@ -137,10 +165,18 @@ static void emit_expression(vec_t* fnlst, tree_t* p_tree, int depth) { } } else if (is_formtype(p_tree, "fn")) { - printf("make(fn,&fn%d)", get_fn_id(fnlst, p_tree)); + printf("__func(&fn%d)", get_fn_id(fnlst, p_tree)); } else { - vec_t* vec = p_tree->ptr.vec; - printf("apply(%s, ", (char*)get_val(vec_at(vec,0))); + vec_t* vec = p_tree->ptr.vec; + size_t nargs = vec_size(vec)-1; + /* Determine the calling convention based on number of args */ + if (0 == nargs) + printf("__call0(%s", (char*)get_val(vec_at(vec,0))); + else if (nargs < 16) + printf("__calln(%s, %d, ", (char*)get_val(vec_at(vec,0)), nargs); + else + printf("__calln(%s, n, ", (char*)get_val(vec_at(vec,0))); + /* Print out the arguments */ for (size_t idx = 1; idx < vec_size(vec); idx++) { emit_expression(fnlst, (tree_t*)vec_at(vec,idx), depth); if (idx+1 < vec_size(vec)) diff --git a/source/sclpl/lexer.c b/source/sclpl/lexer.c index d88fb25..c95c5f8 100644 --- a/source/sclpl/lexer.c +++ b/source/sclpl/lexer.c @@ -67,7 +67,8 @@ static lex_tok_t* lexer_make_token(char* text) { } else if (lexer_oneof("()[]{};,'", text[0])) { p_tok = lexer_punc(text); } else if ('"' == text[0]) { - p_tok = lex_tok_new(T_STRING, lexer_dup(text)); + text[strlen(text)-1] = '\0'; + p_tok = lex_tok_new(T_STRING, lexer_dup(&text[1])); } else if (text[0] == '\\') { p_tok = lexer_char(text); } else if ((text[0] == '0') && lexer_oneof("bodh",text[1])) { diff --git a/source/sclpl/main.c b/source/sclpl/main.c index c010236..a4ae5ba 100644 --- a/source/sclpl/main.c +++ b/source/sclpl/main.c @@ -106,7 +106,8 @@ static int emit_csource(void) { ret = 1; } } - codegen_csource(stdout, p_vec); + if (0 == ret) + codegen_csource(stdout, p_vec); mem_release(p_vec); mem_release(p_parser); return ret; @@ -146,8 +147,6 @@ static int emit_program(void) { * Formalize grammar for parser * Paren for function application must be on same line as variable in REPL - * skip line on error and terminate after full program parse - * skip line and print on error but do not terminate the REPL */ int main(int argc, char **argv) { diff --git a/source/sclpl/pprint.c b/source/sclpl/pprint.c index 166276d..b6f9758 100644 --- a/source/sclpl/pprint.c +++ b/source/sclpl/pprint.c @@ -59,7 +59,7 @@ void pprint_token_type(FILE* file, lex_tok_t* token) { void pprint_token_value(FILE* file, lex_tok_t* token) { void* value = token->value; switch(token->type) { - case T_STRING: fprintf(file, "%s", ((char*)value)); break; + case T_STRING: fprintf(file, "\"%s\"", ((char*)value)); break; case T_CHAR: print_char(file, ((char)(int)value)); break; case T_INT: fprintf(file, "%ld", *((long int*)value)); break; case T_FLOAT: fprintf(file, "%f", *((double*)value)); break; diff --git a/spec/codegen_spec.rb b/spec/codegen_spec.rb index d827bf0..70cb9ae 100644 --- a/spec/codegen_spec.rb +++ b/spec/codegen_spec.rb @@ -29,6 +29,11 @@ def w() 0; def x(a) 1; def y(a,b) 2; def z fn(a,b,c) 3;; + +w() +x(1) +y(1,2) +z(1,2,3) eos ExpectedCode = <<-eos @@ -59,10 +64,12 @@ _Value v; _Value w; _Value x; _Value y; +_Value z; static _Value fn0(); static _Value fn1(_Value a); static _Value fn2(_Value a, _Value b); +static _Value fn3(_Value a, _Value b, _Value c); static _Value fn0() { return __int(0); @@ -76,7 +83,13 @@ static _Value fn2(_Value a, _Value b) { return __int(2); } +static _Value fn3(_Value a, _Value b, _Value c) { + return __int(3); +} + void toplevel(void) { + extern void foo_toplevel(void); + foo_toplevel(); a = __int(123); b = __int(123); c = __int(-123); @@ -102,6 +115,11 @@ void toplevel(void) { w = __func(&fn0); x = __func(&fn1); y = __func(&fn2); + z = __func(&fn3); + (void)(__call0(w)); + (void)(__calln(x, 1, __int(1))); + (void)(__calln(y, 2, __int(1), __int(2))); + (void)(__calln(z, 3, __int(1), __int(2), __int(3))); } int main(int argc, char** argv) { @@ -114,7 +132,6 @@ eos describe "code generation" do it "should generate some code" do - pending "busted" expect(ccode(InputSource)).to eq ExpectedCode end end -- 2.52.0