diff --git a/src/ast.ts b/src/ast.ts index d9172d3..e5e3dc8 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -14,7 +14,8 @@ interface ASTResolveResults { abstract class ASTNode { public abstract resolve( - results: ASTResolveResults + results: ASTResolveResults, + returnType: DataType ): void; public abstract marker(): Token; diff --git a/src/ast_expr.ts b/src/ast_expr.ts index 62c4e13..8c2c72c 100644 --- a/src/ast_expr.ts +++ b/src/ast_expr.ts @@ -46,7 +46,8 @@ class ExprASTBool implements ExpressionAST { } public resolve( - results: ASTResolveResults + results: ASTResolveResults, + returnType: DataType ): void { } public marker(): Token { @@ -83,7 +84,8 @@ class ExprASTString implements ExpressionAST { } public resolve( - results: ASTResolveResults + results: ASTResolveResults, + returnType: DataType ): void { } public marker(): Token { @@ -143,7 +145,10 @@ class ExprASTInt implements ExpressionAST { ); } - public resolve(results: ASTResolveResults): void { + public resolve( + results: ASTResolveResults, + returnType: DataType + ): void { switch(this.bit) { case 4: this.minMaxFlow( @@ -223,7 +228,10 @@ class ExprASTFloat implements ExpressionAST { return LLVMDataType.getFloatDataType(this.bit); } - public resolve(): void { } + public resolve( + results: ASTResolveResults, + returnType: DataType + ): void { } public marker(): Token { return this.mark; @@ -295,7 +303,10 @@ class ExprASTUnary implements ExpressionAST { return this.expr.type(); } - public resolve(results: ASTResolveResults): void { + public resolve( + results: ASTResolveResults, + returnType: DataType + ): void { const dataType: DataType = this.expr.type(); const mrk: Token = this.marker(); @@ -416,7 +427,10 @@ class ExprASTEquality implements ExpressionAST { return DataType.BOOL; } - public resolve(results: ASTResolveResults): void { + public resolve( + results: ASTResolveResults, + returnType: DataType + ): void { const leftType: DataType = this.left.type(); const rightType: DataType = @@ -467,8 +481,8 @@ class ExprASTEquality implements ExpressionAST { ' is not allowed.' ); - this.left.resolve(results); - this.right.resolve(results); + this.left.resolve(results, returnType); + this.right.resolve(results, returnType); } public marker(): Token { @@ -556,7 +570,8 @@ class ExprASTAndOr implements ExpressionAST { } public resolve( - results: ASTResolveResults + results: ASTResolveResults, + returnType: DataType ): void { const leftType: DataType = this.left.type(); @@ -600,9 +615,8 @@ class ExprASTAndOr implements ExpressionAST { ); } - - this.left.resolve(results); - this.right.resolve(results); + this.left.resolve(results, returnType); + this.right.resolve(results, returnType); } public marker(): Token { diff --git a/src/ast_stmt.ts b/src/ast_stmt.ts index f64b9ba..c064651 100644 --- a/src/ast_stmt.ts +++ b/src/ast_stmt.ts @@ -7,7 +7,7 @@ import { FunctionType, ConstantInt, Value, - ReturnInst + Type } from "llvm-bindings"; import { @@ -64,8 +64,14 @@ class StmtASTMain implements StatementAST { } public resolve( - results: ASTResolveResults - ): void { } + results: ASTResolveResults, + returnType: DataType + ): void { + this.body.resolve( + results, + returnType.getLLVMType() as unknown as DataType + ); + } public marker(): Token { return this.mark; @@ -115,8 +121,14 @@ class StmtASTRender implements StatementAST { ); } - public resolve(results: ASTResolveResults): void { - this.expr.resolve(results); + public resolve( + results: ASTResolveResults, + returnType: DataType + ): void { + this.expr.resolve( + results, + returnType + ); } public marker(): Token { @@ -154,10 +166,25 @@ class StmtASTReturn implements StatementAST { } public resolve( - results: ASTResolveResults + results: ASTResolveResults, + returnType: DataType ): void { - if(this.hasValue) - this.value?.resolve(results); + if(this.hasValue) { + const valueType: DataType = + this.value?.type() as DataType; + + if(valueType != returnType) + results.errors.set( + this.mark, + 'Invalid return type ' + + valueType.toString() + ' for type ' + + returnType.toString() + '.'); + + this.value?.resolve( + results, + returnType + ); + } } public marker(): Token { diff --git a/src/data_type.ts b/src/data_type.ts index 1f6a22c..030c763 100644 --- a/src/data_type.ts +++ b/src/data_type.ts @@ -30,6 +30,8 @@ class DataType { public static UNKNOWN: DataType = new DataType("unknown", 0, undefined); + public static VOID: DataType = + new DataType("void", 0, Type.getVoidTy(LLVMGlobalContext)); public static STRING: DataType = new DataType("string", 0, undefined); public static BOOL: DataType = diff --git a/src/yttria.ts b/src/yttria.ts index e0cf8f2..631c8b8 100644 --- a/src/yttria.ts +++ b/src/yttria.ts @@ -1,6 +1,7 @@ import { IRBuilder, Module, + Type, verifyModule } from 'llvm-bindings'; @@ -17,11 +18,8 @@ import { import { ExprASTAndOr, ExprASTBool, - ExprASTEquality, ExprASTFloat, - ExprASTInt, - ExprASTString, - ExprASTUnary + ExprASTInt } from './ast_expr'; import { @@ -35,6 +33,8 @@ import colors from 'colors'; import LLVMGlobalContext from './llvm_context'; import yargs from 'yargs'; import YttriaUtil from './util'; +import { File } from 'buffer'; +import { DataType } from './data_type'; function tokenizerTest() { var tokenizer = new Tokenizer( @@ -42,6 +42,7 @@ function tokenizerTest() { '#hello\nsub main\n0b0101011 0xcafebabe hh 3.14 "Hello\\tworld!" +++ <<< >>>' ); var tokenizerResult: TokenizerResult = tokenizer.scan(); + const outType: Type = Type.getVoidTy(LLVMGlobalContext) if(tokenizerResult.tokens.length != 0) { console.log('Tokens:'); @@ -68,9 +69,14 @@ function llvmTest() { const expr1: ExprASTInt = new ExprASTInt(nullToken, BigInt('101'), 32); const expr2: ExprASTInt = new ExprASTInt(nullToken, BigInt('99'), 32); + const cmp: ExprASTAndOr = new ExprASTAndOr(nullToken, '&', expr1, expr2); const body: StmtASTRender = new StmtASTRender(nullToken, cmp); - const main: StmtASTMain = new StmtASTMain(nullToken, body); + + const main: StmtASTMain = new StmtASTMain( + nullToken, + body + ); const builder: IRBuilder = new IRBuilder(LLVMGlobalContext); main.visit(builder, module);