]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
Added spec for C code generator (still busted). Enabled optimization for the main...
authorMichael D. Lowis <mike@mdlowis.com>
Fri, 17 Oct 2014 19:52:38 +0000 (15:52 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Fri, 17 Oct 2014 19:52:38 +0000 (15:52 -0400)
Rakefile
source/sclpl/codegen.c
source/sclpl/grammar.c
spec/codegen_spec.rb [new file with mode: 0644]
spec/lexer_spec.rb
spec/parser_spec.rb
spec/spec_helper.rb

index 565caa505898b05f183f95cc386609007e4629a7..30519006f523c8a05c5e1dc2d41b87b7defe26af 100644 (file)
--- a/Rakefile
+++ b/Rakefile
@@ -18,6 +18,10 @@ base_env = BuildEnv.new(echo: :command) do |env|
   env["CPPPATH"] += ['modules/libopts/source'] + Dir['modules/libcds/source/**/']
 end
 
+main_env = base_env.clone do |env|
+  env["CFLAGS"] += ['-O3']
+end
+
 test_env = base_env.clone do |env|
   env.build_dir('source','build/obj/test/source')
   env.build_dir('modules','build/obj/test/modules')
@@ -64,16 +68,16 @@ task :build => [:clang, :sclpl]
 
 desc "Build the sclpl compiler and interpreter"
 task :sclpl => [:libcds, :libopts] do
-  base_env.Program('build/bin/sclpl',
+  main_env.Program('build/bin/sclpl',
     FileList['source/sclpl/*.c', 'build/lib/libopts.a', 'build/lib/libcds.a'])
 end
 
 task :libcds do
-  base_env.Library('build/lib/libcds.a', FileList['modules/libcds/source/**/*.c'])
+  main_env.Library('build/lib/libcds.a', FileList['modules/libcds/source/**/*.c'])
 end
 
 task :libopts do
-  base_env.Library('build/lib/libopts.a', FileList['modules/libopts/source/**/*.c'])
+  main_env.Library('build/lib/libopts.a', FileList['modules/libopts/source/**/*.c'])
 end
 
 #------------------------------------------------------------------------------
@@ -103,6 +107,6 @@ RSpec::Core::RakeTask.new(:spec) do |t,args|
   t.rspec_opts = ['--format', 'documentation']
   test_env.Program('build/bin/sclpl-test',
     FileList['source/sclpl/*.c', 'build/lib/libopts.a', 'build/lib/libcds.a'])
-  base_env.process
+  main_env.process
   test_env.process
 end
index 071a491d163ffdc29ec1fea06ab37cad94fdc557..8bc9324131553284798bba59828b2ae7a5b10cb2 100644 (file)
@@ -85,45 +85,7 @@ static void print_indent(int depth) {
 }
 
 static void emit_header(void) {
-    //puts("#include <sclpl.h>\n");
-    printf(
-        "\n#include <stdbool.h>"
-        "\n"
-        "\ntypedef void* _Value;"
-        "\n"
-        "\n#define NIL ((_Value) 0)"
-        "\n#define apply(a,...) ((_Value)0)"
-        "\n#define IF(cnd) (cnd)?"
-        "\n#define ELSE    :"
-        "\n"
-        "\n#define make(type, value) \\"
-        "\n    make_ ## type (value)"
-        "\n"
-        "\nstatic _Value make_string(const char* val) {"
-        "\n    return NIL;"
-        "\n}"
-        "\n"
-        "\nstatic _Value make_char(char val) {"
-        "\n    return NIL;"
-        "\n}"
-        "\n"
-        "\nstatic _Value make_int(long int val) {"
-        "\n    return NIL;"
-        "\n}"
-        "\n"
-        "\nstatic _Value make_float(double val) {"
-        "\n    return NIL;"
-        "\n}"
-        "\n"
-        "\nstatic _Value make_bool(bool val) {"
-        "\n    return NIL;"
-        "\n}"
-        "\n"
-        "\n#define make_fn(value) make_func((void*)(value))"
-        "\nstatic _Value make_func(void* val) {"
-        "\n    return NIL;"
-        "\n}"
-    );
+    puts("#include <sclpl.h>\n");
 }
 
 static void emit_fn_signature(char* name, tree_t* fnval) {
@@ -151,12 +113,12 @@ 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("make(string,'%s')", ((char*)tok->value));              break;
-            case T_CHAR:   printf("make(char,\\%c)",   ((char)(int)tok->value));          break;
-            case T_INT:    printf("make(int,%ld)",     *((long int*)tok->value));         break;
-            case T_FLOAT:  printf("make(float,%f)",    *((double*)tok->value));           break;
-            case T_BOOL:   printf("make(bool,%s)",     ((int)tok->value)?"true":"false"); break;
-            case T_VAR:    printf("%s",                ((char*)tok->value));              break;
+            case T_STRING: printf("__string(%s)", ((char*)tok->value));              break;
+            case T_CHAR:   printf("__char('%c')", ((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;
+            case T_VAR:    printf("%s",           ((char*)tok->value));              break;
         }
     } else if (is_formtype(p_tree, "if")) {
         printf("IF (");
index 9083d2f597fdf47f3d2fdc9cc2b1d821074f6dcb..40b9502f8b408602e925d5ca63eed4b1c6b7a06f 100644 (file)
@@ -28,7 +28,7 @@ tree_t* grammar_toplevel(parser_t* p_parser)
 void grammar_require(parser_t* p_parser)
 {
     size_t mark = parser_mark(p_parser);
-    parser_expect(p_parser, T_VAR);
+    parser_expect(p_parser, T_STRING);
     parser_expect(p_parser, T_END);
     parser_reduce(p_parser, mark);
 }
diff --git a/spec/codegen_spec.rb b/spec/codegen_spec.rb
new file mode 100644 (file)
index 0000000..d827bf0
--- /dev/null
@@ -0,0 +1,120 @@
+require 'spec_helper'
+
+InputSource = <<-eos
+require "foo";
+def a 123;
+def b +123;
+def c -123;
+def d 321.0;
+def e +321.0;
+def f -321.0;
+def g 0b101;
+def h 0o707;
+def i 0d909;
+def j 0hF0F;
+def k 0hf0f;
+def l \\space;
+def m \\tab;
+def n \\return;
+def o \\newline;
+def p \\vtab;
+def q \\c;
+def r "";
+def s "
+";
+def t true;
+def u false;
+def v l;
+def w() 0;
+def x(a) 1;
+def y(a,b) 2;
+def z fn(a,b,c) 3;;
+eos
+
+ExpectedCode = <<-eos
+#include <sclpl.h>
+
+_Value a;
+_Value b;
+_Value c;
+_Value d;
+_Value e;
+_Value f;
+_Value g;
+_Value h;
+_Value i;
+_Value j;
+_Value k;
+_Value l;
+_Value m;
+_Value n;
+_Value o;
+_Value p;
+_Value q;
+_Value r;
+_Value s;
+_Value t;
+_Value u;
+_Value v;
+_Value w;
+_Value x;
+_Value y;
+
+static _Value fn0();
+static _Value fn1(_Value a);
+static _Value fn2(_Value a, _Value b);
+
+static _Value fn0() {
+    return __int(0);
+}
+
+static _Value fn1(_Value a) {
+    return __int(1);
+}
+
+static _Value fn2(_Value a, _Value b) {
+    return __int(2);
+}
+
+void toplevel(void) {
+    a = __int(123);
+    b = __int(123);
+    c = __int(-123);
+    d = __float(321.000000);
+    e = __float(321.000000);
+    f = __float(-321.000000);
+    g = __int(5);
+    h = __int(455);
+    i = __int(909);
+    j = __int(3855);
+    k = __int(3855);
+    l = __char(' ');
+    m = __char('\\t');
+    n = __char('\\r');
+    o = __char('\\n');
+    p = __char('\\v');
+    q = __char('c');
+    r = __string("");
+    s = __string("\\n");
+    t = __bool(true);
+    u = __bool(false);
+    v = l;
+    w = __func(&fn0);
+    x = __func(&fn1);
+    y = __func(&fn2);
+}
+
+int main(int argc, char** argv) {
+    (void)argc;
+    (void)argv;
+    toplevel();
+    return 0;
+}
+eos
+
+describe "code generation" do
+  it "should generate some code" do
+    pending "busted"
+    expect(ccode(InputSource)).to eq ExpectedCode
+  end
+end
index 7857634ef4da1b9958e378a9eddf64ce2c26fd8f..51a81b12293570ab5b068cb72a4277dfc97dd58d 100644 (file)
@@ -144,10 +144,14 @@ describe "lexer" do
       expect(lexer('"a"')).to eq ['T_STRING:"a"']
     end
 
-    it "should recognize a string with one element" do
+    it "should recognize a string with two elements" do
       expect(lexer('"ab"')).to eq ['T_STRING:"ab"']
     end
 
+    it "should recognize a string with a space" do
+      expect(lexer('"a b"')).to eq ['T_STRING:"a b"']
+    end
+
     it "should recognize a string that spans lines" do
       expect(lexer("\"a\nb\"")).to eq ["T_STRING:\"a\nb\""]
     end
index dda0c4d2575c078753c5d49eafe4eca120939cca..57016cafd3fe455898de678dbdeaf8b389fffc28 100644 (file)
@@ -3,15 +3,15 @@ require 'open3'
 describe "sclpl grammar" do
   context "requires" do
     it "should parse a require statement" do
-      expect(ast('require foo;')).to eq([ ['T_VAR:require', 'T_VAR:foo'] ])
+      expect(ast('require "foo";')).to eq([ ['T_VAR:require', 'T_STRING:"foo"'] ])
     end
 
     it "should parse a require statement using end keyword" do
-        expect(ast('require foo end')).to eq([ ['T_VAR:require', 'T_VAR:foo'] ])
+        expect(ast('require "foo" end')).to eq([ ['T_VAR:require', 'T_STRING:"foo"'] ])
     end
 
     it "should error on missing semicolon" do
-      expect{ast('require foo')}.to raise_error /Invalid Syntax/
+      expect{ast('require "foo"')}.to raise_error /Invalid Syntax/
     end
 
     it "should error on missing filename" do
index 521a46380a77e44c5757a76c2a406820c25f02ef..ea3dcaacdb53dd213efa7f84a35720d8c30176f8 100644 (file)
@@ -49,3 +49,9 @@ def ast(input)
   expr
 end
 
+def ccode(input)
+  out, err, status = Open3.capture3('./build/bin/sclpl-test', '--csource', :stdin_data => input)
+  raise err unless err == ""
+  raise "Parser command returned non-zero status" unless status.success?
+  out
+end