Browse Source

tests added

Nicolas Winkler 6 years ago
parent
commit
77dea98f94

+ 0 - 4
src/CodegenVisitor.cpp

@@ -213,10 +213,6 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::FieldAccessExpression& access,
     }
     }
     
     
     llvm::Value* target = access.target->accept(fg.lvalueVisitor, fg);
     llvm::Value* target = access.target->accept(fg.lvalueVisitor, fg);
-    llvm::raw_os_ostream os(Printer::getInstance());
-    type->print(os);
-    os << "\n";
-    os.flush();
 
 
     int structIndex = access.accessed->llvmStructIndex;
     int structIndex = access.accessed->llvmStructIndex;
     llvm::ArrayRef<Value*> indexList = {
     llvm::ArrayRef<Value*> indexList = {

+ 2 - 4
src/ast/Ast.cpp

@@ -6,11 +6,9 @@
 
 
 using namespace qlow::ast;
 using namespace qlow::ast;
 
 
-void Ast::merge(Ast&& other)
+void Ast::merge(Ast other)
 {
 {
-    objects.insert(objects.end(),
-                   std::make_move_iterator(other.objects.begin()),
-                   std::make_move_iterator(other.objects.end()));
+    std::move(other.objects.begin(), other.objects.end(), std::back_inserter(this->objects));
 }
 }
 
 
 
 

+ 16 - 1
src/ast/Ast.h

@@ -44,6 +44,8 @@ namespace qlow
         // base class
         // base class
         struct AstObject;
         struct AstObject;
 
 
+        struct ImportDeclaration;
+
         struct Class;
         struct Class;
 
 
         struct Type;
         struct Type;
@@ -104,7 +106,7 @@ public:
     inline const OwningList<AstObject>& getObjects(void) const  { return objects; }
     inline const OwningList<AstObject>& getObjects(void) const  { return objects; }
     inline       OwningList<AstObject>& getObjects(void)        { return objects; }
     inline       OwningList<AstObject>& getObjects(void)        { return objects; }
 
 
-    void merge(Ast&& other);
+    void merge(Ast other);
 };
 };
 
 
 
 
@@ -120,6 +122,19 @@ struct qlow::ast::AstObject :
 };
 };
 
 
 
 
+struct qlow::ast::ImportDeclaration
+{
+    CodePosition pos;
+    std::string imported;
+    
+    inline ImportDeclaration(std::string imported, const CodePosition& cp) :
+        pos{ cp },
+        imported{ std::move(imported) }
+    {
+    }
+};
+
+
 struct qlow::ast::Class : public AstObject
 struct qlow::ast::Class : public AstObject
 {
 {
     std::string name;
     std::string name;

+ 7 - 0
src/ast/Parser.cpp

@@ -25,3 +25,10 @@ qlow::ast::Ast Parser::parse(void)
 
 
     return result;
     return result;
 }
 }
+
+
+void Parser::addImports(std::vector<std::unique_ptr<ImportDeclaration>> toAdd)
+{
+    std::move(toAdd.begin(), toAdd.end(), std::back_inserter(this->imports));
+
+}

+ 3 - 0
src/ast/Parser.h

@@ -17,12 +17,15 @@ class qlow::ast::Parser
 {
 {
     FILE* stream;
     FILE* stream;
     std::string filename;
     std::string filename;
+    std::vector<std::unique_ptr<ImportDeclaration>> imports;
 public:
 public:
     inline Parser(FILE* stream, std::string filename) :
     inline Parser(FILE* stream, std::string filename) :
         stream{ stream }, filename{ std::move(filename) } {}
         stream{ stream }, filename{ std::move(filename) } {}
     
     
     Ast parse(void);
     Ast parse(void);
 
 
+    void addImports(std::vector<std::unique_ptr<ImportDeclaration>> toAdd);
+
     inline const std::string& getFilename(void) const { return filename; }
     inline const std::string& getFilename(void) const { return filename; }
 };
 };
 
 

+ 1 - 0
src/ast/lexer.l

@@ -103,6 +103,7 @@ UTF8CHAR [\x00-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xe
 "return"                return SET_TOKEN(RETURN);
 "return"                return SET_TOKEN(RETURN);
 "new"                   return SET_TOKEN(NEW);
 "new"                   return SET_TOKEN(NEW);
 "extern"                return SET_TOKEN(EXTERN);
 "extern"                return SET_TOKEN(EXTERN);
+"import"                return SET_TOKEN(IMPORT);
 
 
 ":"                     return SET_TOKEN(COLON);
 ":"                     return SET_TOKEN(COLON);
 ";"                     return SET_TOKEN(SEMICOLON);
 ";"                     return SET_TOKEN(SEMICOLON);

+ 27 - 3
src/ast/syntax.y

@@ -91,7 +91,7 @@ while (0)
 %lex-param   { yyscan_t scanner }
 %lex-param   { yyscan_t scanner }
 %parse-param { yyscan_t scanner }
 %parse-param { yyscan_t scanner }
 %parse-param { qlow::ast::Ast& ast }
 %parse-param { qlow::ast::Ast& ast }
-%parse-param { const qlow::ast::Parser& parser }
+%parse-param { qlow::ast::Parser& parser }
 
 
 
 
 %define api.prefix {qlow_parser_}
 %define api.prefix {qlow_parser_}
@@ -149,6 +149,9 @@ while (0)
     qlow::ast::NewArrayExpression* newArrayExpression;
     qlow::ast::NewArrayExpression* newArrayExpression;
     qlow::ast::CastExpression* castExpression;
     qlow::ast::CastExpression* castExpression;
 
 
+    qlow::ast::ImportDeclaration* importDeclaration;
+    std::vector<std::unique_ptr<qlow::ast::ImportDeclaration>>* importList;
+
     const char* cString;
     const char* cString;
     std::string* string;
     std::string* string;
     int token;
     int token;
@@ -159,12 +162,15 @@ while (0)
 %token <string> INT_LITERAL
 %token <string> INT_LITERAL
 %token <string> ASTERISK SLASH PLUS MINUS EQUALS NOT_EQUALS AND OR XOR CUSTOM_OPERATOR
 %token <string> ASTERISK SLASH PLUS MINUS EQUALS NOT_EQUALS AND OR XOR CUSTOM_OPERATOR
 %token <token> TRUE FALSE
 %token <token> TRUE FALSE
-%token <token> CLASS STRUCT DO END IF ELSE WHILE RETURN NEW EXTERN AS
+%token <token> CLASS STRUCT DO END IF ELSE WHILE RETURN NEW AS
+%token <token> EXTERN IMPORT
 %token <token> NEW_LINE
 %token <token> NEW_LINE
 %token <token> SEMICOLON COLON COMMA DOT ASSIGN AMPERSAND
 %token <token> SEMICOLON COLON COMMA DOT ASSIGN AMPERSAND
 %token <token> ROUND_LEFT ROUND_RIGHT SQUARE_LEFT SQUARE_RIGHT
 %token <token> ROUND_LEFT ROUND_RIGHT SQUARE_LEFT SQUARE_RIGHT
 %token <string> UNEXPECTED_SYMBOL
 %token <string> UNEXPECTED_SYMBOL
 
 
+%type <importDeclaration> importDeclaration
+%type <importList> importList
 %type <topLevel> topLevel
 %type <topLevel> topLevel
 %type <classDefinition> classDefinition
 %type <classDefinition> classDefinition
 %type <type> type
 %type <type> type
@@ -216,7 +222,9 @@ while (0)
 
 
 /* list of class definitions */
 /* list of class definitions */
 topLevel:
 topLevel:
-    /* empty */ {
+    importList {
+       parser.addImports(std::move(*$1));
+       delete $1; $1 = nullptr;
        $$ = &ast;
        $$ = &ast;
     }
     }
     |
     |
@@ -254,6 +262,22 @@ topLevel:
         $3 = nullptr;
         $3 = nullptr;
     };
     };
 
 
+importList:
+    /* empty */ {
+        $$ = new std::vector<std::unique_ptr<qlow::ast::ImportDeclaration>>();
+    }
+    |
+    importList importDeclaration {
+        $$ = $1;
+        $$->emplace_back($2);
+        $2 = nullptr;
+    };
+
+importDeclaration:
+    IMPORT IDENTIFIER {
+        $$ = new qlow::ast::ImportDeclaration(std::move(*$2), @2);
+        delete $2; $2 = nullptr;
+    };
 
 
 classDefinition:
 classDefinition:
     CLASS IDENTIFIER featureList END {
     CLASS IDENTIFIER featureList END {

+ 0 - 1
src/sem/Type.cpp

@@ -129,7 +129,6 @@ size_t Type::hash(void) const
         type
         type
     );
     );
     auto h = type.index() * 2542345234523 + value1;
     auto h = type.index() * 2542345234523 + value1;
-    Printer::getInstance() << h << std::endl;
     return h;
     return h;
 }
 }
 
 

+ 2 - 2
src/tests/structs.qlw

@@ -1,6 +1,6 @@
+import std
 
 
-
-struct Vec
+class Vec
     x: Integer
     x: Integer
     y: Integer
     y: Integer
 
 

+ 48 - 0
tests/runTests.py

@@ -0,0 +1,48 @@
+#!/usr/bin/python
+
+import sys
+import os
+import subprocess
+import difflib
+
+
+if len(sys.argv) <= 1:
+    print("please specify the qlow executable as a command line argument")
+    exit()
+
+qlow_executable = sys.argv[1]
+
+succeeded = 0
+failed = 0
+
+def test_file(path):
+    test = [qlow_executable, path, "-o", path + ".o"]
+    print("running test " + " ".join(test))
+    output = subprocess.run(test, stdout=subprocess.PIPE)
+    with open(path + ".c.did", "w") as out:
+        out.write(output.stdout.decode("utf-8"))
+    
+    with open(path + ".c.did", "r") as did, open(path + ".c.should", "r") as should:
+        if did.readlines() == should.readlines():
+            global succeeded
+            succeeded += 1
+        else:
+            global failed
+            failed += 1
+
+
+
+def run_directory(dir):
+    for root, dirs, files in os.walk(dir):
+        for filename in files:
+            if filename.endswith(".qlw"):
+                test_file(os.path.join(root, filename))
+
+def print_results():
+    print("%d out of %d tests succeeded: %d%%" % (succeeded, succeeded + failed, 100 * succeeded / (succeeded + failed)))
+
+run_directory(".")
+
+print_results()
+
+

+ 15 - 0
tests/syntax/class.qlw

@@ -0,0 +1,15 @@
+class A
+    field: Integer
+    field2: B
+end
+
+class B
+    field: A
+end
+
+
+main do
+    a: A
+    a := new A
+end
+

+ 0 - 0
tests/syntax/class.qlw.c.should


+ 1 - 1
vim/syntax/qlow.vim

@@ -12,7 +12,7 @@ endif
 syntax match commenty "//.*"
 syntax match commenty "//.*"
 syntax region multicommenty start="/\*"  end="\*/" contains=multicommenty
 syntax region multicommenty start="/\*"  end="\*/" contains=multicommenty
 
 
-syn keyword keywordy class struct do end if while return extern as new
+syn keyword keywordy class struct do end if while return extern as new import
 syn keyword typey Integer Boolean Abool
 syn keyword typey Integer Boolean Abool
 syn keyword typey String Char 
 syn keyword typey String Char 
 syn keyword typey Float32 Float64
 syn keyword typey Float32 Float64