diff --git a/example.w b/example.w index 51b8942..c329c6b 100644 --- a/example.w +++ b/example.w @@ -1,6 +1,16 @@ +interface Increments +{ + Increment(): void; +} + struct YourStruct { yourInt: int; + + IncrementOther(other: T): void + { + other.Increment(); + } } struct MyStruct diff --git a/generators/wraith.lex b/generators/wraith.lex index f288c6e..1cf6fa9 100644 --- a/generators/wraith.lex +++ b/generators/wraith.lex @@ -13,6 +13,7 @@ "string" return STRING; "bool" return BOOL; "struct" return STRUCT; +"interface" return INTERFACE; "return" return RETURN; "static" return STATIC; "Reference" return REFERENCE; diff --git a/generators/wraith.y b/generators/wraith.y index 7aaf70a..69a4a9b 100644 --- a/generators/wraith.y +++ b/generators/wraith.y @@ -26,6 +26,7 @@ extern FILE *yyin; %token STRING %token BOOL %token STRUCT +%token INTERFACE %token RETURN %token STATIC %token REFERENCE @@ -307,14 +308,40 @@ Body : LEFT_BRACE Statements RIGHT_BRACE $$ = $2; } -FunctionSignature : Identifier LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type +GenericConstraint : Identifier COLON Identifier { - $$ = MakeFunctionSignatureNode($1, $6, $3, MakeFunctionModifiersNode(NULL, 0)); + $$ = MakeGenericConstraintNode($1, $3); + } + +GenericConstraints : GenericConstraint + { + $$ = StartGenericConstraintsNode($1); + } + | GenericConstraints COMMA GenericConstraint + { + $$ = AddGenericConstraint($1, $3); + } + ; + +GenericConstraintClause : LESS_THAN GenericConstraints GREATER_THAN + { + $$ = $2; + } + | + { + $$ = MakeEmptyGenericConstraintsNode(); + } + ; + +/* FIXME: modifiers should be recursive */ +FunctionSignature : Identifier GenericConstraintClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type + { + $$ = MakeFunctionSignatureNode($1, $7, $4, MakeFunctionModifiersNode(NULL, 0), $2); } | STATIC Identifier LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type { Node *modifier = MakeStaticNode(); - $$ = MakeFunctionSignatureNode($2, $7, $4, MakeFunctionModifiersNode(&modifier, 1)); + $$ = MakeFunctionSignatureNode($2, $7, $4, MakeFunctionModifiersNode(&modifier, 1), MakeEmptyGenericConstraintsNode()); } FunctionDeclaration : FunctionSignature Body @@ -327,6 +354,24 @@ StructDeclaration : STRUCT Identifier LEFT_BRACE Declarations RIGHT_BRACE $$ = MakeStructDeclarationNode($2, $4); } +InterfaceDeclaration : INTERFACE Identifier LEFT_BRACE InterfaceChildren RIGHT_BRACE + { + $$ = MakeInterfaceDeclarationNode($2, $4); + } + +InterfaceChild : FunctionSignature SEMICOLON + ; + +InterfaceChildren : InterfaceChild + { + $$ = StartDeclarationSequenceNode($1); + } + | InterfaceChildren InterfaceChild + { + $$ = AddDeclarationNode($1, $2); + } + ; + Declaration : FunctionDeclaration | VariableDeclaration SEMICOLON ; @@ -340,7 +385,9 @@ Declarations : Declaration $$ = AddDeclarationNode($1, $2); } -TopLevelDeclaration : StructDeclaration; +TopLevelDeclaration : StructDeclaration + | InterfaceDeclaration + ; TopLevelDeclarations : TopLevelDeclaration { diff --git a/src/ast.c b/src/ast.c index 4f33a63..28cd79f 100644 --- a/src/ast.c +++ b/src/ast.c @@ -286,20 +286,59 @@ Node *MakeEmptyFunctionSignatureArgumentsNode() return node; } +Node* MakeGenericConstraintNode(Node *identifierNode, Node *interfaceNode) +{ + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = GenericConstraint; + node->childCount = 2; + node->children = (Node**) malloc(sizeof(Node*) * 2); + node->children[0] = identifierNode; + node->children[1] = interfaceNode; + return node; +} + +Node* StartGenericConstraintsNode(Node *genericNode) +{ + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = GenericConstraints; + node->childCount = 1; + node->children = (Node**) malloc(sizeof(Node*)); + node->children[0] = genericNode; + return node; +} + +Node* AddGenericConstraint(Node *genericsNode, Node *genericNode) +{ + genericsNode->children = realloc(genericsNode->children, sizeof(Node*) * (genericsNode->childCount + 1)); + genericsNode->children[genericsNode->childCount] = genericNode; + genericsNode->childCount += 1; + return genericsNode; +} + +Node* MakeEmptyGenericConstraintsNode() +{ + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = GenericConstraints; + node->childCount = 0; + return node; +} + Node* MakeFunctionSignatureNode( Node *identifierNode, Node* typeNode, Node* arguments, - Node* modifiersNode + Node* modifiersNode, + Node* genericConstraintsNode ) { Node* node = (Node*) malloc(sizeof(Node)); node->syntaxKind = FunctionSignature; - node->childCount = 4; + node->childCount = 5; node->children = (Node**) malloc(sizeof(Node*) * (node->childCount)); node->children[0] = identifierNode; node->children[1] = typeNode; node->children[2] = arguments; node->children[3] = modifiersNode; + node->children[4] = genericConstraintsNode; return node; } @@ -329,6 +368,19 @@ Node* MakeStructDeclarationNode( return node; } +Node* MakeInterfaceDeclarationNode( + Node *identifierNode, + Node *declarationSequenceNode +) { + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = InterfaceDeclaration; + node->childCount = 2; + node->children = (Node**) malloc(sizeof(Node*) * 2); + node->children[0] = identifierNode; + node->children[1] = declarationSequenceNode; + return node; +} + Node* StartDeclarationSequenceNode( Node *declarationNode ) { diff --git a/src/ast.h b/src/ast.h index 8e49ace..3ddbe7d 100644 --- a/src/ast.h +++ b/src/ast.h @@ -21,9 +21,12 @@ typedef enum FunctionModifiers, FunctionSignature, FunctionSignatureArguments, + GenericConstraint, + GenericConstraints, Identifier, IfStatement, IfElseStatement, + InterfaceDeclaration, Number, PrimitiveTypeNode, ReferenceTypeNode, @@ -154,21 +157,36 @@ Node* AddFunctionSignatureArgumentNode( Node *argumentsNode, Node *argumentNode ); -Node *MakeEmptyFunctionSignatureArgumentsNode(); +Node* MakeEmptyFunctionSignatureArgumentsNode(); +Node* MakeGenericConstraintNode( + Node *identifierNode, + Node *interfaceNode +); +Node* StartGenericConstraintsNode(Node *genericNode); +Node* AddGenericConstraint( + Node *genericsNode, + Node *genericNode +); +Node* MakeEmptyGenericConstraintsNode(); Node* MakeFunctionSignatureNode( Node *identifierNode, - Node* typeNode, - Node* argumentsNode, - Node* modifiersNode + Node *typeNode, + Node *argumentsNode, + Node *modifiersNode, + Node *genericConstraintsNode ); Node* MakeFunctionDeclarationNode( - Node* functionSignatureNode, - Node* functionBodyNode + Node *functionSignatureNode, + Node *functionBodyNode ); Node* MakeStructDeclarationNode( Node *identifierNode, Node *declarationSequenceNode ); +Node* MakeInterfaceDeclarationNode( + Node *identifierNode, + Node *declarationSequenceNode +); Node* StartDeclarationSequenceNode( Node *declarationNode ); diff --git a/src/codegen.c b/src/codegen.c index 3e75d1b..b5e9bf6 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -984,6 +984,11 @@ static void CompileStruct(LLVMModuleRef module, LLVMContextRef context, Node *no PopScopeFrame(scope); } +static void CompileInterface(LLVMModuleRef module, LLVMContextRef context, Node *node) +{ + +} + static void Compile(LLVMModuleRef module, LLVMContextRef context, Node *node) { uint32_t i; @@ -994,9 +999,13 @@ static void Compile(LLVMModuleRef module, LLVMContextRef context, Node *node) { CompileStruct(module, context, node->children[i]); } + else if (node->children[i]->syntaxKind == InterfaceDeclaration) + { + CompileInterface(module, context, node->children[i]); + } else { - fprintf(stderr, "top level declarations that are not structs are forbidden!\n"); + fprintf(stderr, "Top-level declarations that are not structs or interfaces are forbidden!\n"); } } }