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')
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
#------------------------------------------------------------------------------
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
}
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) {
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 (");
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);
}
--- /dev/null
+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
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
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
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