]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
Added basic recognition of types and type annotations master
authorMichael D. Lowis <mike@mdlowis.com>
Wed, 31 Aug 2016 02:14:02 +0000 (22:14 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Wed, 31 Aug 2016 02:14:02 +0000 (22:14 -0400)
.gitignore
Makefile
source/lexer.l
source/parser.c
source/pprint.c
source/sclpl.h
spec/parser_spec.rb

index 4bf735a9d0005d46f392d0e61e5e61d375b849be..c85b4557b4f59cb9ff8f25bb203f0c5a60ddab22 100644 (file)
@@ -12,3 +12,4 @@ cscope.out
 .rsconscache
 sclpl
 source/lexer.c
+project.vim
index 7fb63fefe817c6a622abba9836730d572fc00480..8136bc96f127ebbfd89a2722fd5254bc4d0d9d9a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -32,8 +32,8 @@ TESTBIN  = testsclpl
 TESTOBJS = tests/atf.o        \
            tests/sclpl/main.o
 
-.PHONY: all options tests specs
-all: sclpl specs tests
+.PHONY: all tests specs
+all: sclpl tests specs
 
 lib${BIN}.a: ${OBJS}
        ${AR} ${ARFLAGS} $@ $^
@@ -41,11 +41,11 @@ lib${BIN}.a: ${OBJS}
 ${BIN}: lib${BIN}.a
        ${LD} ${LDFLAGS} -o $@ $^
 
-${TESTBIN}: ${TESTOBJS}
-       ${LD} ${LDFLAGS} -o $@ $^
+#${TESTBIN}: ${TESTOBJS}
+#      ${LD} ${LDFLAGS} -o $@ $^
 
-tests: $(TESTBIN)
-       ./$<
+#tests: ${TESTBIN}
+#      ./$<
 
 specs: $(BIN)
        rspec --pattern 'spec/**{,/*/**}/*_spec.rb' --format documentation
index 9f949a25ac3d0b56a188a5a0c30ecf80088807a1..a076a4c7e0cdfdbad7a2e6f7fe1b8265f110257b 100644 (file)
@@ -43,6 +43,7 @@ NOSPACE [^ \t\r\n]
 ","   { return T_COMMA;  }
 "'"   { return T_SQUOTE; }
 ":"   { return T_COLON;  }
+"&"   { return T_AMP;    }
 
 \\.       { Value.character = yytext[1];    return T_CHAR; }
 \\space   { Value.character = ' ';          return T_CHAR; }
index 1b0840bf2416ad125158f74699a2398487d6878a..3bd066c92ead00fe22e04a34631f592aacd163d8 100644 (file)
@@ -21,6 +21,7 @@ static AST* literal(Parser* p);
 static AST* expr_block(Parser* p);
 static AST* token_to_tree(Tok* tok);
 static AST* func_app(Parser* p, AST* fn);
+static void optional_type(Parser* p);
 
 // Parsing Routines
 static void parser_free(void* obj);
@@ -56,6 +57,7 @@ static AST* definition(Parser* p)
     if (peek(p)->type == T_LPAR) {
         expr = function(p);
     } else {
+        optional_type(p);
         expr = expression(p);
         expect(p, T_END);
     }
@@ -109,10 +111,12 @@ static AST* function(Parser* p)
     expect(p, T_LPAR);
     while(peek(p)->type != T_RPAR) {
         func_add_arg(func, Ident(expect(p,T_ID)));
+        optional_type(p);
         if(peek(p)->type != T_RPAR)
             expect(p, T_COMMA);
     }
     expect(p, T_RPAR);
+    optional_type(p);
     func_set_body(func, expr_block(p));
     expect(p, T_END);
     return func;
@@ -188,6 +192,21 @@ static AST* func_app(Parser* p, AST* fn)
     return app;
 }
 
+static void optional_type(Parser* p)
+{
+    if (accept(p, T_COLON)) {
+        expect(p, T_ID);
+        /* array type */
+        if (accept(p,T_LBRACK)) {
+            accept(p, T_INT);
+            expect(p, T_RBRACK);
+        /* reference type */
+        } else if (accept(p, T_AMP)) {
+
+        }
+    }
+}
+
 /* Parsing Routines
  *****************************************************************************/
 Parser* parser_new(char* prompt, FILE* input)
index 048e7dff89891b6cfd61dc72750dba727fce48b2..f8bb6514c7ae3c3c309a145bef38b97aae661db0 100644 (file)
@@ -28,6 +28,7 @@ static const char* token_type_to_string(TokType type) {
         case T_ID:       return "T_ID";
         case T_END:      return "T_END";
         case T_COLON:    return "T_COLON";
+        case T_AMP:      return "T_AMP";
         case T_SQUOTE:   return "T_SQUOTE";
         case T_DQUOTE:   return "T_DQUOTE";
         case T_END_FILE: return "T_END_FILE";
index 64fff927275e11f618f918f347bfb21a10c98fd6..9ba913c766cc89fee133540e73d9590309e0f15b 100644 (file)
@@ -51,7 +51,7 @@ void vec_set(vec_t* vec, size_t index, void* data);
  *****************************************************************************/
 typedef enum {
     T_ID, T_CHAR, T_INT, T_FLOAT, T_BOOL, T_STRING, T_LBRACE, T_RBRACE, T_LBRACK,
-    T_RBRACK, T_LPAR, T_RPAR, T_COMMA, T_SQUOTE, T_DQUOTE, T_END, T_COLON,
+    T_RBRACK, T_LPAR, T_RPAR, T_COMMA, T_SQUOTE, T_DQUOTE, T_END, T_COLON, T_AMP,
     T_REQUIRE, T_DEF, T_IF, T_FN, T_THEN, T_ELSE, T_END_FILE
 } TokType;
 
@@ -82,6 +82,7 @@ typedef struct AST {
         /* Definition Node */
         struct {
             char* name;
+            struct AST* type;
             struct AST* value;
         } def;
         /* If Expression */
index 0f7376c6f839bdb485ba029b02691ec00eb94677..59ad238afd8562444016d22793936c6c85291adb 100644 (file)
@@ -94,12 +94,31 @@ describe "sclpl grammar" do
       expect(ast('def foo 123;')).to eq([ ['def', 'foo', 'T_INT:123'] ])
     end
 
+    it "should error on missing type for definiton" do
+      expect{ast('def foo : 123;')}.to raise_error /Error/
+    end
+
+    it "should parse a value definition with type annotation" do
+      expect(ast('def foo:int 123;')).to eq([ ['def', 'foo', 'T_INT:123'] ])
+    end
+
     it "should parse a function definition" do
       expect(ast('def foo() 123;')).to eq([
         ['def', 'foo', ['fn', [],
           ["let", ["$:0", "T_INT:123"], "$:0"]]] ])
     end
 
+    it "should parse a function definition with return type annotation" do
+      expect(ast('def foo():int 123;')).to eq([
+        ['def', 'foo', ['fn', [],
+          ["let", ["$:0", "T_INT:123"], "$:0"]]] ])
+    end
+
+    it "should error on a function definition with missing return type" do
+      pending("TODO: fix the error message here")
+      expect(ast('def foo() : 123;')).to raise_error /Error/
+    end
+
     it "should parse a function definition  with multiple expressions in the body" do
       expect(ast('def foo() 123 321;')).to eq([
         ['def', 'foo', ['fn', [],
@@ -151,12 +170,24 @@ describe "sclpl grammar" do
             ["let", ["$:0", "T_INT:123"], "$:0"]]])
       end
 
+      it "should parse a function with no params and a return type annotation" do
+        expect(ast('fn():int 123;')).to eq([
+          ["fn", [],
+            ["let", ["$:0", "T_INT:123"], "$:0"]]])
+      end
+
       it "should parse a function with one param" do
         expect(ast('fn(a) 123;')).to eq([
           ["fn", ["T_ID:a"],
             ["let", ["$:0", "T_INT:123"], "$:0"]]])
       end
 
+      it "should parse a function with one param with type annotation" do
+        expect(ast('fn(a:int) 123;')).to eq([
+          ["fn", ["T_ID:a"],
+            ["let", ["$:0", "T_INT:123"], "$:0"]]])
+      end
+
       it "should parse a function with two params" do
         expect(ast('fn(a,b) 123;')).to eq([
           ["fn", ["T_ID:a", "T_ID:b"],