diff --git a/.gitignore b/.gitignore index 76add87..c9d5ba4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ node_modules -dist \ No newline at end of file +dist +examples/* +!examples/*.gom \ No newline at end of file diff --git a/examples/functions.gom b/examples/functions.gom deleted file mode 100644 index f055a6c..0000000 --- a/examples/functions.gom +++ /dev/null @@ -1,3 +0,0 @@ -import io; - -type Values = [int]; \ No newline at end of file diff --git a/examples/hello_world.ll b/examples/hello_world.ll index e74b4a0..ee19ae7 100644 --- a/examples/hello_world.ll +++ b/examples/hello_world.ll @@ -4,11 +4,15 @@ source_filename = "mod" @.strliteral = private unnamed_addr constant [14 x i8] c"Hello, World!\00", align 1 @newline = private unnamed_addr constant [2 x i8] c"\0A\00", align 1 +declare i32 @printf(i8*, ...) + +declare i8* @malloc(i32) + +declare i8* @realloc(i8*, i32) + define void @main() { entry: %calltmp0 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.strliteral, i32 0, i32 0)) %newline = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @newline, i32 0, i32 0)) ret void } - -declare i32 @printf(i8*, ...) diff --git a/examples/list b/examples/list index 8a07bae..5063336 100755 Binary files a/examples/list and b/examples/list differ diff --git a/examples/loop b/examples/loop index 2b525e9..03dccd7 100755 Binary files a/examples/loop and b/examples/loop differ diff --git a/examples/loop.ll b/examples/loop.ll index 8d518b9..2561a84 100644 --- a/examples/loop.ll +++ b/examples/loop.ll @@ -13,6 +13,8 @@ declare i32 @printf(i8*, ...) declare i8* @malloc(i32) +declare i8* @realloc(i8*, i32) + define void @main() { entry: %i = alloca i32, align 4 diff --git a/examples/readme b/examples/readme index 09c068d..512ebf2 100755 Binary files a/examples/readme and b/examples/readme differ diff --git a/examples/test_2 b/examples/test_2 index 6277a72..f9ba4f3 100755 Binary files a/examples/test_2 and b/examples/test_2 differ diff --git a/examples/test_3 b/examples/test_3 index 8ec9a11..f812334 100755 Binary files a/examples/test_3 and b/examples/test_3 differ diff --git a/run.ts b/run.ts index 1fedd87..d41f225 100755 --- a/run.ts +++ b/run.ts @@ -1,6 +1,7 @@ #!/usr/bin/env tsx import { runCompile } from "./src/index"; import { execSync } from "node:child_process"; +import { logGreen } from "./src/util/console"; const filePath = process.argv[2]; const target = (process.argv[3] || "c") as "c" | "llvm"; @@ -12,13 +13,11 @@ runCompile(filePath, target) execSync( `clang -o ${filePath.replace(".gom", "")} ${filePath.replace( ".gom", - ".ll" + ".ll", )}`, - { stdio: "inherit" } - ); - console.log( - `✅ Executable generated at: ${filePath.replace(".gom", "")}` + { stdio: "inherit" }, ); + logGreen(`Executable generated at: ${filePath.replace(".gom", "")}`); } }) .catch((error) => { diff --git a/src/codegen/c.ts b/src/codegen/c.ts index 503a8d1..1209bdc 100644 --- a/src/codegen/c.ts +++ b/src/codegen/c.ts @@ -4,7 +4,7 @@ import { writeFileSync } from "node:fs"; import { BaseCodeGenerator } from "./common"; -import { GomPrimitiveTypeOrAlias } from "../semantics/type"; +import { GomPrimitiveTypeOrAlias } from "../types"; import { NodeAccess, NodeAssignment, @@ -135,7 +135,7 @@ export class CodeGenerator extends BaseCodeGenerator { visitLetStatement(node: NodeLetStatement): void { for (const decl of node.decls) { const type = this.mapGomTypeToC( - decl.lhs.resultantType as GomPrimitiveTypeOrAlias + decl.lhs.gomType as GomPrimitiveTypeOrAlias, ); const rhsValue = this.visitExpression(decl.rhs); @@ -183,7 +183,7 @@ export class CodeGenerator extends BaseCodeGenerator { visitForStatement(node: NodeForStatement): void { if (node.initExpr && node.conditionExpr && node.updateExpr) { - const initValue = this.visitExpression(node.initExpr); + const initValue = this.visitExpression(node.initExpr as NodeExpr); const conditionValue = this.visitExpression(node.conditionExpr); const updateValue = this.visitExpression(node.updateExpr); diff --git a/src/codegen/common.ts b/src/codegen/common.ts index 2679e45..48b40aa 100644 --- a/src/codegen/common.ts +++ b/src/codegen/common.ts @@ -31,7 +31,7 @@ export abstract class BaseCodeGenerator extends SimpleVisitor { this.outputPath = outputPath; this.errorManager = errorManager; this.symbolTableReader = new SymbolTableReader( - scopeManager.getCurrentSymbolTableNode() + scopeManager.getCurrentSymbolTableNode(), ); } diff --git a/src/codegen/llvm.ts b/src/codegen/llvm.ts index 0c9289e..5bf155c 100644 --- a/src/codegen/llvm.ts +++ b/src/codegen/llvm.ts @@ -35,7 +35,7 @@ import { GomStructType, GomTupleType, GomType, -} from "../semantics/type"; +} from "../types"; import { GomToken } from "../lexer/tokens"; import { GomErrorManager } from "../util/error"; import { Node } from "../parser/rd/tree"; @@ -98,7 +98,7 @@ export class CodeGenerator extends BaseCodeGenerator { globalVariables.forEach((id) => { const type = this.mapGomTypeToLLVMType( - id.type as GomPrimitiveTypeOrAlias + id.type as GomPrimitiveTypeOrAlias, ); const global = new llvm.GlobalVariable( this.module, @@ -106,7 +106,7 @@ export class CodeGenerator extends BaseCodeGenerator { false, llvm.Function.LinkageTypes.ExternalLinkage, null, - id.name + id.name, ); if (id.valueExpr) { @@ -137,7 +137,7 @@ export class CodeGenerator extends BaseCodeGenerator { private mapGomTupleTypeToLLVMType(type: GomTupleType) { const types = Array.from(type.fields).map((t) => - this.mapGomTypeToLLVMType(t[1]) + this.mapGomTypeToLLVMType(t[1]), ); return llvm.StructType.get(this.context, types); } @@ -208,7 +208,7 @@ export class CodeGenerator extends BaseCodeGenerator { }[t]); this.formatStrings[type] = this.builder.CreateGlobalStringPtr( `${typeToFormatString(type) || "%d"}`, - `fmt.${type}` + `fmt.${type}`, ); } @@ -219,7 +219,7 @@ export class CodeGenerator extends BaseCodeGenerator { const printFnType = llvm.FunctionType.get( this.builder.getInt32Ty(), [llvm.Type.getInt8PtrTy(this.context)], - true + true, ); this.module.getOrInsertFunction("printf", printFnType); @@ -227,7 +227,7 @@ export class CodeGenerator extends BaseCodeGenerator { const mallocFnType = llvm.FunctionType.get( this.builder.getInt8PtrTy(), [this.builder.getInt32Ty()], - false + false, ); this.module.getOrInsertFunction("malloc", mallocFnType); @@ -235,7 +235,7 @@ export class CodeGenerator extends BaseCodeGenerator { const reallocFnType = llvm.FunctionType.get( this.builder.getInt8PtrTy(), [this.builder.getInt8PtrTy(), this.builder.getInt32Ty()], - false + false, ); this.module.getOrInsertFunction("realloc", reallocFnType); } @@ -268,7 +268,7 @@ export class CodeGenerator extends BaseCodeGenerator { } const structType = llvm.StructType.create( this.context, - node.name.token.value + node.name.token.value, ); const gomType = type.gomType as GomStructType; const fields = Array.from(gomType.fields).map(([_key, fieldType]) => { @@ -287,7 +287,7 @@ export class CodeGenerator extends BaseCodeGenerator { } const tupleType = llvm.StructType.create( this.context, - node.name.token.value + node.name.token.value, ); const gomType = type.gomType as GomTupleType; const fields = Array.from(gomType.fields).map(([_key, fieldType]) => { @@ -305,7 +305,7 @@ export class CodeGenerator extends BaseCodeGenerator { } const listType = llvm.StructType.create( this.context, - node.name.token.value + node.name.token.value, ); const gomType = type.gomType as GomListType; const elementType = this.mapGomTypeToLLVMType(gomType.elementType); @@ -322,11 +322,11 @@ export class CodeGenerator extends BaseCodeGenerator { visitFunctionDefinition(node: NodeFunctionDefinition): void { this.symbolTableReader.enterScope(node.name.value); this.irScopeManager.enterScope(node.name.value); - const fnType = node.resultantType as GomFunctionType; + const fnType = node.gomType as GomFunctionType; const returnTypeGom = fnType.returnType; const returnType = this.mapGomTypeToLLVMType(returnTypeGom); - const argsType = (node.resultantType as GomFunctionType).args.map((arg) => - this.mapGomTypeToLLVMType(arg as GomPrimitiveTypeOrAlias) + const argsType = (node.gomType as GomFunctionType).args.map((arg) => + this.mapGomTypeToLLVMType(arg as GomPrimitiveTypeOrAlias), ); if (fnType.usesSret()) { @@ -337,13 +337,13 @@ export class CodeGenerator extends BaseCodeGenerator { const funcType = llvm.FunctionType.get( fnType.usesSret() ? llvm.Type.getVoidTy(this.context) : returnType, argsType, - false + false, ); const fn = llvm.Function.Create( funcType, llvm.Function.LinkageTypes.ExternalLinkage, node.name.value, - this.module + this.module, ); if (fnType.usesSret()) { @@ -383,7 +383,7 @@ export class CodeGenerator extends BaseCodeGenerator { funcType, llvm.Function.LinkageTypes.ExternalLinkage, "main", - this.module + this.module, ); const entry = llvm.BasicBlock.Create(this.context, "entry", mainFunction); @@ -414,7 +414,7 @@ export class CodeGenerator extends BaseCodeGenerator { true, llvm.GlobalValue.LinkageTypes.PrivateLinkage, llvm.ConstantInt.get(type, Number(decl.rhs.token.value)), - decl.lhs.token.value + decl.lhs.token.value, ); } continue; @@ -422,11 +422,11 @@ export class CodeGenerator extends BaseCodeGenerator { // this.builder.SetInsertPoint(this.currentFunctionEntry); - const type = this.mapGomTypeToLLVMType(decl.lhs.resultantType); + const type = this.mapGomTypeToLLVMType(decl.lhs.gomType); const alloca = this.builder.CreateAlloca( type, null, - decl.lhs.token.value + decl.lhs.token.value, ); const id = this.symbolTableReader.getIdentifier(decl.lhs.token.value); @@ -439,8 +439,6 @@ export class CodeGenerator extends BaseCodeGenerator { pointer: alloca, }); - console.log("RHS Value:", rhsValue, "Type:", rhsValue.getType()); - if (!type.isStructTy()) { this.builder.CreateStore(rhsValue, alloca); } @@ -460,7 +458,7 @@ export class CodeGenerator extends BaseCodeGenerator { } if (node.expr) { - if (node.expr.resultantType instanceof GomPrimitiveTypeOrAlias) { + if (node.expr.gomType instanceof GomPrimitiveTypeOrAlias) { const exprValue = this.visitExpression(node.expr); this.builder.CreateRet(exprValue); } else { @@ -489,17 +487,17 @@ export class CodeGenerator extends BaseCodeGenerator { const thenBB = llvm.BasicBlock.Create( this.context, "then", - currentFunction + currentFunction, ); const elseBB = llvm.BasicBlock.Create( this.context, "else", - currentFunction + currentFunction, ); const mergeBB = llvm.BasicBlock.Create( this.context, "merge", - currentFunction + currentFunction, ); this.builder.CreateCondBr(condValue, thenBB, elseBB); @@ -545,22 +543,22 @@ export class CodeGenerator extends BaseCodeGenerator { const loopBB = llvm.BasicBlock.Create( this.context, "loop", - currentFunction + currentFunction, ); const bodyBB = llvm.BasicBlock.Create( this.context, "loopbody", - currentFunction + currentFunction, ); const updateBB = llvm.BasicBlock.Create( this.context, "loopupdate", - currentFunction + currentFunction, ); const afterBB = llvm.BasicBlock.Create( this.context, "afterloop", - currentFunction + currentFunction, ); if (node.initExpr instanceof NodeLetStatement) { @@ -598,12 +596,12 @@ export class CodeGenerator extends BaseCodeGenerator { const loopBB = llvm.BasicBlock.Create( this.context, "infloop", - currentFunction + currentFunction, ); const afterBB = llvm.BasicBlock.Create( this.context, "afterinfloop", - currentFunction + currentFunction, ); this.builder.CreateBr(loopBB); @@ -644,7 +642,7 @@ export class CodeGenerator extends BaseCodeGenerator { const after = llvm.BasicBlock.Create( this.context, "after.break", - this.currentFunction! + this.currentFunction!, ); this.builder.SetInsertPoint(after); } @@ -664,7 +662,7 @@ export class CodeGenerator extends BaseCodeGenerator { const after = llvm.BasicBlock.Create( this.context, "after.continue", - this.currentFunction! + this.currentFunction!, ); this.builder.SetInsertPoint(after); } @@ -701,7 +699,6 @@ export class CodeGenerator extends BaseCodeGenerator { message: "Unknown identifier: " + node.lhs.token.value, }); } - console.log(id); const rhsValue = this.visitExpression(node.rhs); this.builder.CreateStore(rhsValue, id.allocaInst!); return rhsValue; @@ -709,11 +706,11 @@ export class CodeGenerator extends BaseCodeGenerator { visitStructInit( node: NodeStructInit, - context?: ExpressionContext + context?: ExpressionContext, ): llvm.Value { if (context?.declLhs) { const structId = this.symbolTableReader.getIdentifier( - context.declLhs.token.value + context.declLhs.token.value, ); if (!structId) { this.errorManager.throwCodegenError({ @@ -729,7 +726,7 @@ export class CodeGenerator extends BaseCodeGenerator { }); } const structAlloca = structId.allocaInst; - const structType = this.mapGomTypeToLLVMType(node.resultantType); + const structType = this.mapGomTypeToLLVMType(node.gomType); const index0 = this.builder.getInt32(0); node.fields.forEach((field, i) => { const fieldVal = this.visitExpression(field[1]); @@ -737,17 +734,17 @@ export class CodeGenerator extends BaseCodeGenerator { structType, structAlloca, [index0, this.builder.getInt32(i)], - "fieldptr" + "fieldptr", ); this.builder.CreateStore(fieldVal, fieldPtr); }); return structAlloca; } else { - const structType = this.mapGomTypeToLLVMType(node.resultantType); + const structType = this.mapGomTypeToLLVMType(node.gomType); const structAlloca = this.builder.CreateAlloca( structType, null, - node.structTypeName.token.value + "_instance" + node.structTypeName.token.value + "_instance", ); node.fields.forEach((field, i) => { const fieldVal = this.visitExpression(field[1]); @@ -755,7 +752,7 @@ export class CodeGenerator extends BaseCodeGenerator { structType, structAlloca, [this.builder.getInt32(0), this.builder.getInt32(i)], - "fieldptr" + "fieldptr", ); this.builder.CreateStore(fieldVal, fieldPtr); }); @@ -765,12 +762,10 @@ export class CodeGenerator extends BaseCodeGenerator { visitCollectionInit( node: NodeCollectionInit, - context?: ExpressionContext + context?: ExpressionContext, ): llvm.Value { - if (node.resultantType instanceof GomTupleType) { - const type = this.mapGomTypeToLLVMType( - node.resultantType as GomTupleType - ); + if (node.gomType instanceof GomTupleType) { + const type = this.mapGomTypeToLLVMType(node.gomType as GomTupleType); const tuple = this.builder.CreateAlloca(type, null, "tuple"); node.elements.forEach((element, i) => { const fieldVal = this.visitExpression(element); @@ -778,13 +773,13 @@ export class CodeGenerator extends BaseCodeGenerator { type, tuple, [this.builder.getInt32(0), this.builder.getInt32(i)], - "fieldptr" + "fieldptr", ); this.builder.CreateStore(fieldVal, fieldPtr); }); return tuple; - } else if (node.resultantType instanceof GomListType) { - const gomListType = node.resultantType as GomListType; + } else if (node.gomType instanceof GomListType) { + const gomListType = node.gomType as GomListType; const listType = this.mapGomTypeToLLVMType(gomListType); // const listPtr = this.builder.CreateAlloca(listType, null, "list_ptr"); const listPtr = context?.pointer @@ -795,42 +790,40 @@ export class CodeGenerator extends BaseCodeGenerator { listType, listPtr, [this.builder.getInt32(0), this.builder.getInt32(0)], - "data_ptr_ptr" + "data_ptr_ptr", ); const sizePtr = this.builder.CreateGEP( listType, listPtr, [this.builder.getInt32(0), this.builder.getInt32(1)], - "size_ptr" + "size_ptr", ); const capacityPtr = this.builder.CreateGEP( listType, listPtr, [this.builder.getInt32(0), this.builder.getInt32(2)], - "capacity_ptr" + "capacity_ptr", ); const initialCapacity = this.builder.getInt32( - Math.max(LIST_INITIAL_CAPACITY, node.elements.length) + Math.max(LIST_INITIAL_CAPACITY, node.elements.length), ); this.builder.CreateStore(initialCapacity, capacityPtr); this.builder.CreateStore( this.builder.getInt32(node.elements.length), - sizePtr + sizePtr, ); const elementType = this.mapGomTypeToLLVMType(gomListType.elementType); - console.log("Element type:", elementType, gomListType.elementType); const arrayElementType = elementType; const sizeOfType = llvm.ConstantInt.get( llvm.Type.getInt32Ty(this.context), - this.module.getDataLayout().getTypeAllocSize(elementType) + this.module.getDataLayout().getTypeAllocSize(elementType), ); - console.log("Size of type:", sizeOfType); const mallocSize = this.builder.CreateMul( initialCapacity, sizeOfType, - "malloc_size" + "malloc_size", ); const mallocFn = this.module.getFunction("malloc"); if (!mallocFn) { @@ -842,12 +835,12 @@ export class CodeGenerator extends BaseCodeGenerator { const mallocCall = this.builder.CreateCall( mallocFn, [mallocSize], - "malloc_call" + "malloc_call", ); const dataAlloca = this.builder.CreateBitCast( mallocCall, llvm.PointerType.get(arrayElementType, 0), - "data_alloca" + "data_alloca", ); this.builder.CreateStore(dataAlloca, dataPtrPtr); @@ -858,14 +851,14 @@ export class CodeGenerator extends BaseCodeGenerator { elementVal = this.builder.CreateLoad( this.mapGomTypeToLLVMType(gomListType.elementType), elementVal, - "element_load" + "element_load", ); } const elementPtr = this.builder.CreateInBoundsGEP( arrayElementType, dataAlloca, [this.builder.getInt32(i)], - "element_ptr" + "element_ptr", ); this.builder.CreateStore(elementVal, elementPtr); }); @@ -881,9 +874,9 @@ export class CodeGenerator extends BaseCodeGenerator { visitTupleLiteral( node: NodeTupleLiteral, - context?: ExpressionContext + context?: ExpressionContext, ): llvm.Value { - const type = this.mapGomTypeToLLVMType(node.resultantType as GomTupleType); + const type = this.mapGomTypeToLLVMType(node.gomType as GomTupleType); const tuple = context?.pointer ?? this.builder.CreateAlloca(type, null, "tuple"); node.elements.forEach((element, i) => { @@ -892,7 +885,7 @@ export class CodeGenerator extends BaseCodeGenerator { type, tuple, [this.builder.getInt32(0), this.builder.getInt32(i)], - "fieldptr" + "fieldptr", ); this.builder.CreateStore(fieldVal, fieldPtr); }); @@ -923,7 +916,7 @@ export class CodeGenerator extends BaseCodeGenerator { this.builder.CreateCall(fn, [arg], key + i); } else { const formatString = this.getFormatStringLiteralPointer( - (currentArg.resultantType as GomPrimitiveTypeOrAlias).typeString + (currentArg.gomType as GomPrimitiveTypeOrAlias).typeString, ); this.builder.CreateCall(fn, [formatString, arg], key + i); } @@ -933,19 +926,19 @@ export class CodeGenerator extends BaseCodeGenerator { if (!this.globalStringPtrs["newline"]) { this.globalStringPtrs["newline"] = this.builder.CreateGlobalStringPtr( "\n", - "newline" + "newline", ); } const newline = this.globalStringPtrs["newline"]; this.builder.CreateCall(fn, [newline], "newline"); return this.builder.getInt32(0); } else if ( - (node.lhs.resultantType instanceof GomStructType || - node.lhs.resultantType instanceof GomTupleType) && + (node.lhs.gomType instanceof GomStructType || + node.lhs.gomType instanceof GomTupleType) && node.rhs instanceof NodeTerm ) { - const type = node.lhs.resultantType; - const structType = this.mapGomTypeToLLVMType(node.lhs.resultantType); + const type = node.lhs.gomType; + const structType = this.mapGomTypeToLLVMType(node.lhs.gomType); const struct = this.symbolTableReader.getIdentifier(idName); if (!struct) { this.errorManager.throwCodegenError({ @@ -964,7 +957,7 @@ export class CodeGenerator extends BaseCodeGenerator { const index = type instanceof GomStructType ? this.builder.getInt32( - Array.from(type.fields.keys()).indexOf(node.rhs.token.value) + Array.from(type.fields.keys()).indexOf(node.rhs.token.value), ) : this.builder.getInt32(Number(node.rhs.token.value)); @@ -972,19 +965,19 @@ export class CodeGenerator extends BaseCodeGenerator { structType, struct.allocaInst, [this.builder.getInt32(0), index], - "fieldptr" + "fieldptr", ); const load = this.builder.CreateLoad( - this.mapGomTypeToLLVMType(node.rhs.resultantType), + this.mapGomTypeToLLVMType(node.rhs.gomType), ptr, - "fieldload" + "fieldload", ); if (context?.pointer) { this.builder.CreateStore(load, context.pointer); } return load; - } else if (node.lhs.resultantType instanceof GomListType) { - const type = node.lhs.resultantType; + } else if (node.lhs.gomType instanceof GomListType) { + const type = node.lhs.gomType; const listType = this.mapGomTypeToLLVMType(type); const list = this.symbolTableReader.getIdentifier(idName); if (!list) { @@ -1010,12 +1003,12 @@ export class CodeGenerator extends BaseCodeGenerator { listType, list.allocaInst, [this.builder.getInt32(0), this.builder.getInt32(1)], - "size_ptr" + "size_ptr", ); const sizeValue = this.builder.CreateLoad( llvm.Type.getInt32Ty(this.context), sizePtr, - "size_value" + "size_value", ); if (context?.pointer) { this.builder.CreateStore(sizeValue, context.pointer); @@ -1029,24 +1022,24 @@ export class CodeGenerator extends BaseCodeGenerator { listType, list.allocaInst, [this.builder.getInt32(0), this.builder.getInt32(0)], - "data_ptr_ptr" + "data_ptr_ptr", ); const dataPtr = this.builder.CreateLoad( llvm.PointerType.get(elementType, 0), dataPtrPtr, - "data_ptr" + "data_ptr", ); const elementPtr = this.builder.CreateInBoundsGEP( elementType, dataPtr, [indexValue], - "element_ptr" + "element_ptr", ); const load = this.builder.CreateLoad( elementType, elementPtr, - "element_load" + "element_load", ); if (context?.pointer) { this.builder.CreateStore(load, context.pointer); @@ -1109,17 +1102,17 @@ export class CodeGenerator extends BaseCodeGenerator { */ private sizeofBytes(type: llvm.Type): llvm.ConstantInt { return this.builder.getInt32( - this.module.getDataLayout().getTypeAllocSize(type) + this.module.getDataLayout().getTypeAllocSize(type), ); } private handleBuiltinFreeFunctions( fname: "push" | "pop", node: NodeCall, - context?: ExpressionContext + context?: ExpressionContext, ): llvm.Value { const listArg = node.args[0]; - const listType = listArg.resultantType; + const listType = listArg.gomType; if (!(listType instanceof GomListType)) { this.errorManager.throwCodegenError({ loc: node.loc, @@ -1151,19 +1144,19 @@ export class CodeGenerator extends BaseCodeGenerator { listLLVMType, listSym.allocaInst, [this.builder.getInt32(0), this.builder.getInt32(0)], - "list.data.ptrptr" + "list.data.ptrptr", ); const sizePtr = this.builder.CreateInBoundsGEP( listLLVMType, listSym.allocaInst, [this.builder.getInt32(0), this.builder.getInt32(1)], - "list.size.ptr" + "list.size.ptr", ); const capPtr = this.builder.CreateInBoundsGEP( listLLVMType, listSym.allocaInst, [this.builder.getInt32(0), this.builder.getInt32(2)], - "list.cap.ptr" + "list.cap.ptr", ); if (fname === "push") { @@ -1178,12 +1171,12 @@ export class CodeGenerator extends BaseCodeGenerator { const sizeVal = this.builder.CreateLoad( this.builder.getInt32Ty(), sizePtr, - "list.size" + "list.size", ); const capVal = this.builder.CreateLoad( this.builder.getInt32Ty(), capPtr, - "list.cap" + "list.cap", ); // If cap == 0, set to initial; if size >= cap, grow cap *= 2 @@ -1191,12 +1184,12 @@ export class CodeGenerator extends BaseCodeGenerator { const needInitBB = llvm.BasicBlock.Create( this.context, "list.needinit", - currFn + currFn, ); const growthCheckBB = llvm.BasicBlock.Create( this.context, "list.growthcheck", - currFn + currFn, ); const growBB = llvm.BasicBlock.Create(this.context, "list.grow", currFn); const contBB = llvm.BasicBlock.Create(this.context, "list.cont", currFn); @@ -1204,7 +1197,7 @@ export class CodeGenerator extends BaseCodeGenerator { const isZeroCap = this.builder.CreateICmpEQ( capVal, this.builder.getInt32(0), - "cap.iszero" + "cap.iszero", ); this.builder.CreateCondBr(isZeroCap, needInitBB, growthCheckBB); @@ -1215,7 +1208,7 @@ export class CodeGenerator extends BaseCodeGenerator { const initBytes = this.builder.CreateMul( initCap, elemSize, - "list.init.bytes" + "list.init.bytes", ); const mallocFn = this.module.getFunction("malloc"); @@ -1228,12 +1221,12 @@ export class CodeGenerator extends BaseCodeGenerator { const newDataI8 = this.builder.CreateCall( mallocFn, [initBytes], - "list.init.malloc" + "list.init.malloc", ); const newDataPtr = this.builder.CreateBitCast( newDataI8, llvm.PointerType.get(elemLLVMType, 0), - "list.init.dataptr" + "list.init.dataptr", ); this.builder.CreateStore(newDataPtr, dataPtrPtr); this.builder.CreateStore(initCap, capPtr); @@ -1243,16 +1236,16 @@ export class CodeGenerator extends BaseCodeGenerator { this.builder.SetInsertPoint(growthCheckBB); const sizeReload = this.builder.CreateLoad( this.builder.getInt32Ty(), - sizePtr + sizePtr, ); const capReload = this.builder.CreateLoad( this.builder.getInt32Ty(), - capPtr + capPtr, ); const needGrow = this.builder.CreateICmpSGE( sizeReload, capReload, - "list.needgrow" + "list.needgrow", ); this.builder.CreateCondBr(needGrow, growBB, contBB); @@ -1261,13 +1254,13 @@ export class CodeGenerator extends BaseCodeGenerator { const newCap = this.builder.CreateMul( capReload, this.builder.getInt32(2), - "list.newcap" + "list.newcap", ); const elemSize2 = this.sizeofBytes(elemLLVMType); const newBytes = this.builder.CreateMul( newCap, elemSize2, - "list.newbytes" + "list.newbytes", ); const reallocFn = this.module.getFunction("realloc"); @@ -1280,22 +1273,22 @@ export class CodeGenerator extends BaseCodeGenerator { const oldDataPtr = this.builder.CreateLoad( llvm.PointerType.get(elemLLVMType, 0), dataPtrPtr, - "list.olddataptr" + "list.olddataptr", ); const oldDataI8 = this.builder.CreateBitCast( oldDataPtr, this.builder.getInt8PtrTy(), - "list.olddatai8" + "list.olddatai8", ); const grownI8 = this.builder.CreateCall( reallocFn, [oldDataI8, newBytes], - "list.realloc" + "list.realloc", ); const grownPtr = this.builder.CreateBitCast( grownI8, llvm.PointerType.get(elemLLVMType, 0), - "list.growndataptr" + "list.growndataptr", ); this.builder.CreateStore(grownPtr, dataPtrPtr); this.builder.CreateStore(newCap, capPtr); @@ -1306,7 +1299,7 @@ export class CodeGenerator extends BaseCodeGenerator { const dataPtr = this.builder.CreateLoad( llvm.PointerType.get(elemLLVMType, 0), dataPtrPtr, - "list.dataptr" + "list.dataptr", ); // Evaluate value (arg1) @@ -1315,7 +1308,7 @@ export class CodeGenerator extends BaseCodeGenerator { valueToPush = this.builder.CreateLoad( elemLLVMType, valueToPush, - "list.push.load" + "list.push.load", ); } @@ -1323,13 +1316,13 @@ export class CodeGenerator extends BaseCodeGenerator { elemLLVMType, dataPtr, [sizeReload], - "list.elem.ptr" + "list.elem.ptr", ); this.builder.CreateStore(valueToPush, elemPtr); const sizePlusOne = this.builder.CreateAdd( sizeReload, - this.builder.getInt32(1) + this.builder.getInt32(1), ); this.builder.CreateStore(sizePlusOne, sizePtr); @@ -1349,7 +1342,7 @@ export class CodeGenerator extends BaseCodeGenerator { const sizeVal = this.builder.CreateLoad( this.builder.getInt32Ty(), sizePtr, - "list.size" + "list.size", ); const one = this.builder.getInt32(1); const newSize = this.builder.CreateSub(sizeVal, one, "list.newsize"); @@ -1358,18 +1351,18 @@ export class CodeGenerator extends BaseCodeGenerator { const dataPtr = this.builder.CreateLoad( llvm.PointerType.get(elemLLVMType, 0), dataPtrPtr, - "list.dataptr" + "list.dataptr", ); const elemPtr = this.builder.CreateInBoundsGEP( elemLLVMType, dataPtr, [newSize], - "list.elem.ptr" + "list.elem.ptr", ); const value = this.builder.CreateLoad( elemLLVMType, elemPtr, - "list.pop.value" + "list.pop.value", ); if (context?.pointer) { this.builder.CreateStore(value, context.pointer); @@ -1409,14 +1402,14 @@ export class CodeGenerator extends BaseCodeGenerator { this.builder.CreateAlloca( this.mapGomTypeToLLVMType(gomFn.type.returnType), null, - "sret" + "sret", ); const args = node.args.map((arg) => this.visitExpression(arg)); this.builder.CreateCall(fn, [sretPointer, ...args]); return sretPointer; } else { const args = node.args.map((arg) => - this.visitExpression(arg, { pointer: context?.pointer }) + this.visitExpression(arg, { pointer: context?.pointer }), ); return this.builder.CreateCall(fn, args, "calltmp"); } @@ -1455,7 +1448,7 @@ export class CodeGenerator extends BaseCodeGenerator { const loadInst = this.builder.CreateLoad( this.mapGomTypeToLLVMType(id.type as GomPrimitiveTypeOrAlias), id.allocaInst, - id.name + ".load" + id.name + ".load", ); this.builder.CreateStore(loadInst, pointer); return loadInst; @@ -1495,7 +1488,7 @@ export class CodeGenerator extends BaseCodeGenerator { return this.builder.CreateLoad( this.mapGomTypeToLLVMType(id.type as GomPrimitiveTypeOrAlias), id.allocaInst, - id.name + ".load" + id.name + ".load", ); } else if (type === GomToken.TRUE) { return this.builder.getInt1(true); diff --git a/src/index.ts b/src/index.ts index 6714f04..cf4c56e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,67 +6,77 @@ import { RecursiveDescentParser } from "./parser/rd"; import { SemanticAnalyzer } from "./semantics"; import { CodeGenerator as LLVMCodeGenerator } from "./codegen/llvm"; import { CodeGenerator as CCodeGenerator } from "./codegen/c"; -import { GomErrorManager } from "./util/error"; +import { GomError, GomErrorManager } from "./util/error"; import { execSync } from "node:child_process"; +import { TypeAttacher } from "./types/type-attacher"; +import { logBlue, logGreen } from "./util/console"; +import { NodeProgram } from "./parser/rd/nodes"; export const compile = async ( srcPath: string, src: string, - target: "llvm" | "c" + target: "llvm" | "c", ) => { const errorManager = new GomErrorManager(src); - console.time("⏰ Compiled in"); - const lexer = new Lexer(src, errorManager); + let program: NodeProgram | null = null; + const startTime = performance.now(); + try { + const lexer = new Lexer(src, errorManager); - const parser = new RecursiveDescentParser(lexer); + const parser = new RecursiveDescentParser(lexer); - const program = parser.parse(); + program = parser.parse(); - // console.log("Parsed program", program); + new TypeAttacher().visit(program); - const semanticAnalyzer = new SemanticAnalyzer(program, errorManager); - semanticAnalyzer.analyze(); + const semanticAnalyzer = new SemanticAnalyzer(program, errorManager); + semanticAnalyzer.analyze(); - const codeGenerator = - target === "llvm" - ? new LLVMCodeGenerator({ - ast: program, - scopeManager: semanticAnalyzer.scopeManager, - errorManager, - outputPath: srcPath.replace(".gom", ".ll"), - }) - : new CCodeGenerator({ - ast: program, - scopeManager: semanticAnalyzer.scopeManager, - errorManager, - outputPath: srcPath.replace(".gom", ".c"), - }); - codeGenerator.generateAndWriteFile(); + const codeGenerator = + target === "llvm" + ? new LLVMCodeGenerator({ + ast: program, + scopeManager: semanticAnalyzer.scopeManager, + errorManager, + outputPath: srcPath.replace(".gom", ".ll"), + }) + : new CCodeGenerator({ + ast: program, + scopeManager: semanticAnalyzer.scopeManager, + errorManager, + outputPath: srcPath.replace(".gom", ".c"), + }); + codeGenerator.generateAndWriteFile(); + } catch (e) { + if (e instanceof GomError) { + e.print(); + process.exit(1); + } + } if (target === "c") { // Compile the generated C code execSync( `clang -S -emit-llvm ${srcPath.replace( ".gom", - ".c" + ".c", )} -o ${srcPath.replace(".gom", ".ll")}`, - { stdio: "inherit" } + { stdio: "inherit" }, ); execSync( `clang ${srcPath.replace(".gom", ".c")} -o ${srcPath.replace( ".gom", - "" + "", )}`, - { stdio: "inherit" } - ); - console.log( - `✅ Compiled to out, run with ./${srcPath.replace(".gom", "")}` + { stdio: "inherit" }, ); + logGreen(`Compiled to out, run with ./${srcPath.replace(".gom", "")}`); } else { - console.log(`✅ Compiled to ${srcPath.replace(".gom", ".ll")}`); + logGreen(`Compiled to ${srcPath.replace(".gom", ".ll")}`); } - console.timeEnd("⏰ Compiled in"); + const endTime = performance.now(); + logBlue(`Compilation took ${(endTime - startTime).toFixed(2)} ms`); await writeFile( "tree.json", @@ -78,15 +88,15 @@ export const compile = async ( } return val; }, - 2 + 2, ), - "utf-8" + "utf-8", ); }; export const compileAndReturn = async ( src: string, - target: "llvm" | "c" = "llvm" + target: "llvm" | "c" = "llvm", ) => { const errorManager = new GomErrorManager(src); const lexer = new Lexer(src, errorManager); diff --git a/src/parser/rd/index.ts b/src/parser/rd/index.ts index e6064d3..d6f67b9 100644 --- a/src/parser/rd/index.ts +++ b/src/parser/rd/index.ts @@ -66,7 +66,7 @@ export class RecursiveDescentParser { } else { this.errorManager.throwSyntaxError({ message: `Unexpected token: ${chalk.red( - this.token.value + this.token.value, )}, expected ${chalk.green(type)}`, loc: this.token.start, }); @@ -143,10 +143,10 @@ export class RecursiveDescentParser { parseProgram() { const importDeclarations = this.parseZeroOrMore( - this.parseImportDeclaration + this.parseImportDeclaration, ); const typeGlobalOrFunctionDefinitions = this.parseZeroOrMore( - this.parseTypeGlobalOrFunctionDefinition + this.parseTypeGlobalOrFunctionDefinition, ); const mainFunction = this.parseMainFunction(); @@ -154,14 +154,14 @@ export class RecursiveDescentParser { importDeclarations, typeDefinitions: typeGlobalOrFunctionDefinitions.filter( (def): def is NodeTypeDefinition => - def.type === NodeType.TYPE_DEFINITION + def.type === NodeType.TYPE_DEFINITION, ), globalVariables: typeGlobalOrFunctionDefinitions.filter( - (def): def is NodeLetStatement => def.type === NodeType.LET_STATEMENT + (def): def is NodeLetStatement => def.type === NodeType.LET_STATEMENT, ), functionDeclarations: typeGlobalOrFunctionDefinitions.filter( (def): def is NodeFunctionDefinition => - def.type === NodeType.FUNCTION_DEFINITION + def.type === NodeType.FUNCTION_DEFINITION, ), exportStatements: [], mainFunction, @@ -560,7 +560,6 @@ export class RecursiveDescentParser { this.match(GomToken.LBRACE); // could be struct, tuple or list this.buffer.push(this.lexer.nextToken()); - console.log(this.buffer); // @ts-ignore if (this.buffer[1].type === GomToken.COLON) { const fields: [NodeTerm, NodeExpr][] = this.parseOneOrMore(() => { diff --git a/src/parser/rd/nodes/index.ts b/src/parser/rd/nodes/index.ts index bd8de9b..396d217 100644 --- a/src/parser/rd/nodes/index.ts +++ b/src/parser/rd/nodes/index.ts @@ -1,14 +1,5 @@ import { Token } from "../../../lexer"; -import { GomToken } from "../../../lexer/tokens"; -import { - GomCompositeType, - GomCompositeTypeKind, - GomListType, - GomPrimitiveTypeOrAlias, - GomStructType, - GomTupleType, - GomType, -} from "../../../semantics/type"; +import { GomCompositeTypeKind } from "../../../types"; import { AbstractNode, Node, NodeType } from "../tree"; function formChildrenArray(...nodes: (Node | Node[] | undefined)[]): Node[] { @@ -63,7 +54,7 @@ export class NodeProgram extends AbstractNode { typeDefinitions, globalVariables, functionDeclarations, - mainFunction + mainFunction, ); } } @@ -103,7 +94,7 @@ export class NodeTypeDefinition extends AbstractNode { this.loc = loc; this.name = name; this.rhs = rhs; - this.children = []; + this.children = formChildrenArray(name, rhs); } } @@ -114,7 +105,6 @@ export class NodeFunctionDefinition extends AbstractNode { args: NodeArgumentItem[]; returnType?: NodeFunctionReturnType; body: NodeStatement[]; - resultantType: GomType; constructor({ loc, @@ -137,7 +127,6 @@ export class NodeFunctionDefinition extends AbstractNode { this.returnType = returnType; this.body = body; this.children = formChildrenArray(args, returnType, body); - this.resultantType = new GomPrimitiveTypeOrAlias("void"); } } @@ -249,7 +238,7 @@ export class NodeForStatement extends AbstractNode { initExpr, conditionExpr, updateExpr, - body + body, ); } } @@ -339,7 +328,6 @@ export class NodeArgumentItem extends AbstractNode { name: NodeTerm; expectedType: NodeTerm; children: Node[]; - resultantType: GomType; constructor({ name, @@ -356,7 +344,6 @@ export class NodeArgumentItem extends AbstractNode { this.name = name; this.expectedType = expectedType; this.children = []; - this.resultantType = new GomPrimitiveTypeOrAlias("void"); } } @@ -383,7 +370,6 @@ export type NodeGomType = export class NodeGomTypeId extends AbstractNode { type: NodeType; id: NodeTerm; - gomType: GomType; children: Node[]; constructor({ id, loc }: { id: NodeTerm; arrSize?: NodeTerm; loc: number }) { @@ -391,7 +377,6 @@ export class NodeGomTypeId extends AbstractNode { this.type = NodeType.GOM_TYPE_ID; this.loc = loc; this.id = id; - this.gomType = id.resultantType; this.children = []; } } @@ -399,7 +384,6 @@ export class NodeGomTypeId extends AbstractNode { export class NodeGomTypeTuple extends AbstractNode { type: NodeType; fields: NodeGomType[]; - gomType: GomType; children: Node[]; constructor({ fields, loc }: { fields: NodeGomType[]; loc: number }) { @@ -407,15 +391,14 @@ export class NodeGomTypeTuple extends AbstractNode { this.type = NodeType.GOM_TYPE_TUPLE; this.loc = loc; this.fields = fields; - this.gomType = new GomTupleType(fields.map((field) => field.gomType)); this.children = formChildrenArray(fields); } } export class NodeGomTypeStruct extends AbstractNode { type: NodeType; + name: NodeTerm; fields: NodeGomTypeStructField[]; - gomType: GomStructType; constructor({ name, @@ -429,22 +412,16 @@ export class NodeGomTypeStruct extends AbstractNode { super(); this.type = NodeType.GOM_TYPE_STRUCT; this.loc = loc; + this.name = name; this.fields = fields; - this.gomType = new GomStructType( - name.token.value, - fields.reduce((acc, field) => { - acc.set(field.name.value, field.fieldType.gomType); - return acc; - }, new Map()) - ); this.children = formChildrenArray(fields); } } export class NodeGomTypeList extends AbstractNode { type: NodeType; + name: NodeTerm; elementType: NodeGomType; - gomType: GomListType; children: Node[]; constructor({ @@ -459,8 +436,8 @@ export class NodeGomTypeList extends AbstractNode { super(); this.type = NodeType.GOM_TYPE_LIST; this.loc = loc; + this.name = name; this.elementType = elementType; - this.gomType = new GomListType(name.token.value, elementType.gomType); this.children = formChildrenArray(elementType); } } @@ -469,7 +446,6 @@ export class NodeGomTypeComposite extends AbstractNode { type: NodeType; id: NodeTerm; fields: NodeGomType[]; - gomType: GomType; children: Node[]; constructor({ @@ -486,10 +462,6 @@ export class NodeGomTypeComposite extends AbstractNode { this.loc = loc; this.id = id; this.fields = fields; - this.gomType = new GomCompositeType( - NodeGomTypeComposite.getGomCompositeTypeKind(id), - fields.map((field) => field.gomType) - ); this.children = []; } @@ -542,7 +514,6 @@ export class NodeAssignment extends AbstractNode { type: NodeType; lhs: NodeTerm; rhs: NodeExpr; - resultantType: GomType; constructor({ lhs, @@ -558,7 +529,6 @@ export class NodeAssignment extends AbstractNode { this.loc = loc; this.lhs = lhs; this.rhs = rhs; - this.resultantType = new GomPrimitiveTypeOrAlias("void"); this.children = formChildrenArray(lhs, rhs); } } @@ -567,7 +537,6 @@ export class NodeStructInit extends AbstractNode { type: NodeType; structTypeName: NodeTerm; fields: [NodeTerm, NodeExpr][]; - resultantType: GomStructType; constructor({ structTypeName, @@ -583,13 +552,6 @@ export class NodeStructInit extends AbstractNode { this.loc = loc; this.structTypeName = structTypeName; this.fields = fields; - this.resultantType = new GomStructType( - structTypeName.token.value, - fields.reduce((acc, [field, expr]) => { - acc.set(field.token.value, expr.resultantType); - return acc; - }, new Map()) - ); this.children = formChildrenArray(fields.map(([, expr]) => expr)); } } @@ -598,7 +560,6 @@ export class NodeCollectionInit extends AbstractNode { type: NodeType; collectionTypeName: NodeTerm; elements: NodeExpr[]; - resultantType: GomType; constructor({ collectionTypeName, @@ -614,10 +575,6 @@ export class NodeCollectionInit extends AbstractNode { this.loc = loc; this.collectionTypeName = collectionTypeName; this.elements = elements; - this.resultantType = new GomListType( - collectionTypeName.token.value, - elements[0].resultantType - ); this.children = formChildrenArray(elements); } } @@ -627,7 +584,6 @@ export class NodeBinaryOp extends AbstractNode { lhs: NodeExpr; op: Token; rhs: NodeExpr; - resultantType: GomPrimitiveTypeOrAlias; constructor({ loc, @@ -648,7 +604,6 @@ export class NodeBinaryOp extends AbstractNode { this.lhs = lhs; this.op = op; this.rhs = rhs; - this.resultantType = new GomPrimitiveTypeOrAlias("void"); this.children = formChildrenArray(lhs, rhs); } } @@ -657,7 +612,6 @@ export class NodeAccess extends AbstractNode { type: NodeType; lhs: NodeTerm; rhs: NodeExpr; - resultantType: GomType; children: Node[]; constructor({ @@ -674,7 +628,6 @@ export class NodeAccess extends AbstractNode { this.loc = loc; this.lhs = lhs; this.rhs = rhs; - this.resultantType = new GomPrimitiveTypeOrAlias("void"); this.children = formChildrenArray(lhs, rhs); } } @@ -683,7 +636,6 @@ export class NodeCall extends AbstractNode { type: NodeType; id: NodeExpr; args: NodeExpr[]; - resultantType: GomType; children: Node[]; constructor({ @@ -700,7 +652,6 @@ export class NodeCall extends AbstractNode { this.loc = loc; this.id = id; this.args = args; - this.resultantType = new GomPrimitiveTypeOrAlias("void"); this.children = formChildrenArray(id, args); } } @@ -709,14 +660,12 @@ export class NodeExprBracketed extends AbstractNode { type: NodeType; expr: NodeExpr; children: Node[]; - resultantType: GomType; constructor({ expr, loc }: { expr: NodeExpr; loc: number }) { super(); this.type = NodeType.EXPR_BRACKETED; this.loc = loc; this.expr = expr; - this.resultantType = new GomPrimitiveTypeOrAlias("void"); this.children = formChildrenArray(expr); } } @@ -726,7 +675,6 @@ export class NodeIndexedAccess extends AbstractNode { lhs: NodeExpr; index: NodeExpr; children: Node[]; - resultantType: GomType; constructor({ lhs, @@ -743,7 +691,6 @@ export class NodeIndexedAccess extends AbstractNode { this.lhs = lhs; this.index = index; this.children = formChildrenArray(lhs, index); - this.resultantType = new GomPrimitiveTypeOrAlias("void"); } } @@ -751,8 +698,6 @@ export class NodeTupleLiteral extends AbstractNode { type: NodeType; elements: NodeExpr[]; children: Node[]; - gomType: GomType; - resultantType: GomType; constructor({ elements, loc }: { elements: NodeExpr[]; loc: number }) { super(); @@ -760,10 +705,6 @@ export class NodeTupleLiteral extends AbstractNode { this.loc = loc; this.elements = elements; this.children = elements; - this.gomType = new GomTupleType( - elements.map((elements) => elements.resultantType) - ); - this.resultantType = this.gomType; } } @@ -771,8 +712,6 @@ export class NodeTerm extends AbstractNode { type: NodeType; token: Token; children: Node[]; - gomType: GomType; - resultantType: GomType; constructor(token: Token) { super(); @@ -780,25 +719,24 @@ export class NodeTerm extends AbstractNode { this.loc = token.start; this.token = token; this.children = []; - this.resultantType = this.gomType = this.getGomType(); - } - - private getGomType() { - if (this.token.type === GomToken.IDENTIFIER) { - return new GomPrimitiveTypeOrAlias(`resolve_type@@${this.token.value}`); - } else if (this.token.type === GomToken.NUMLITERAL) { - return new GomPrimitiveTypeOrAlias("int"); - } else if (this.token.type === GomToken.STRLITERAL) { - return new GomPrimitiveTypeOrAlias("str"); - } else if ( - this.token.type === GomToken.TRUE || - this.token.type === GomToken.FALSE - ) { - return new GomPrimitiveTypeOrAlias("bool"); - } else if (this.token.type === GomToken.BUILT_IN_TYPE) { - return new GomPrimitiveTypeOrAlias(this.token.value); - } - - throw new Error(`Cannot determine type for token: ${this.token.type}`); } + + // private getGomType() { + // if (this.token.type === GomToken.IDENTIFIER) { + // return new GomPrimitiveTypeOrAlias(`resolve_type@@${this.token.value}`); + // } else if (this.token.type === GomToken.NUMLITERAL) { + // return new GomPrimitiveTypeOrAlias("int"); + // } else if (this.token.type === GomToken.STRLITERAL) { + // return new GomPrimitiveTypeOrAlias("str"); + // } else if ( + // this.token.type === GomToken.TRUE || + // this.token.type === GomToken.FALSE + // ) { + // return new GomPrimitiveTypeOrAlias("bool"); + // } else if (this.token.type === GomToken.BUILT_IN_TYPE) { + // return new GomPrimitiveTypeOrAlias(this.token.value); + // } + + // throw new Error(`Cannot determine type for token: ${this.token.type}`); + // } } diff --git a/src/parser/rd/tree.ts b/src/parser/rd/tree.ts index a74f421..fd1f938 100644 --- a/src/parser/rd/tree.ts +++ b/src/parser/rd/tree.ts @@ -1,4 +1,5 @@ import { Token } from "../../lexer"; +import { GomDeferredType, GomType } from "../../types"; import { Visitor } from "./visitor"; export interface Node { @@ -18,12 +19,14 @@ export abstract class AbstractNode implements Node { parent?: Node; children: Node[]; token?: Token; + gomType: GomType; constructor() { this._id = globalNodeIdCounter++; this.type = NodeType.PROGRAM; this.loc = 0; this.children = []; + this.gomType = new GomDeferredType("deferred", "unknown"); } accept(visitor: Visitor): void { diff --git a/src/parser/rd/visitor.ts b/src/parser/rd/visitor.ts index 1123339..477be59 100644 --- a/src/parser/rd/visitor.ts +++ b/src/parser/rd/visitor.ts @@ -12,7 +12,12 @@ import { NodeForStatement, NodeFunctionDefinition, NodeFunctionReturnType, + NodeGomTypeComposite, + NodeGomTypeId, + NodeGomTypeList, + NodeGomTypeStruct, NodeGomTypeStructField, + NodeGomTypeTuple, NodeIfStatement, NodeImportDeclaration, NodeIndexedAccess, @@ -34,6 +39,12 @@ export interface Visitor { visitProgram(node: NodeProgram): void; visitImportDeclaration(node: NodeImportDeclaration): void; visitTypeDefinition(node: NodeTypeDefinition): void; + visitGomTypeId(node: NodeGomTypeId): void; + visitGomTypeTuple(node: NodeGomTypeTuple): void; + visitGomTypeStruct(node: NodeGomTypeStruct): void; + visitGomTypeList(node: NodeGomTypeList): void; + visitGomTypeComposite(node: NodeGomTypeComposite): void; + visitGomTypeStructField(node: NodeGomTypeStructField): void; visitFunctionDefinition(node: NodeFunctionDefinition): void; visitMainFunction(node: NodeMainFunction): void; visitArgumentItem(node: NodeArgumentItem): void; @@ -49,7 +60,7 @@ export interface Visitor { visitLetStatement(node: NodeLetStatement): void; visitExpressionStatement( node: NodeExpressionStatement, - state: StateType + state: StateType, ): void; visitTerm(node: NodeTerm): void; } @@ -72,6 +83,24 @@ export class SimpleVisitor implements Visitor { case NodeType.TYPE_DEFINITION: this.visitTypeDefinition(node as NodeTypeDefinition); return; + case NodeType.GOM_TYPE_ID: + this.visitGomTypeId(node as NodeGomTypeId); + return; + case NodeType.GOM_TYPE_TUPLE: + this.visitGomTypeTuple(node as NodeGomTypeTuple); + return; + case NodeType.GOM_TYPE_STRUCT: + this.visitGomTypeStruct(node as NodeGomTypeStruct); + return; + case NodeType.GOM_TYPE_LIST: + this.visitGomTypeList(node as NodeGomTypeList); + return; + case NodeType.GOM_TYPE_COMPOSITE: + this.visitGomTypeComposite(node as NodeGomTypeComposite); + return; + case NodeType.GOM_TYPE_STRUCT_FIELD: + this.visitGomTypeStructField(node as NodeGomTypeStructField); + return; case NodeType.FUNCTION_DEFINITION: this.visitFunctionDefinition(node as NodeFunctionDefinition); return; @@ -159,6 +188,24 @@ export class SimpleVisitor implements Visitor { visitTypeDefinition(node: NodeTypeDefinition) { this.visitChildren(node); } + visitGomTypeId(node: NodeGomTypeId) { + this.visitChildren(node); + } + visitGomTypeTuple(node: NodeGomTypeTuple) { + this.visitChildren(node); + } + visitGomTypeStruct(node: NodeGomTypeStruct) { + this.visitChildren(node); + } + visitGomTypeList(node: NodeGomTypeList) { + this.visitChildren(node); + } + visitGomTypeComposite(node: NodeGomTypeComposite) { + this.visitChildren(node); + } + visitGomTypeStructField(node: NodeGomTypeStructField): void { + this.visitChildren(node); + } visitFunctionDefinition(node: NodeFunctionDefinition) { this.visitChildren(node); } diff --git a/src/semantics/index.ts b/src/semantics/index.ts index 926771f..338ea80 100644 --- a/src/semantics/index.ts +++ b/src/semantics/index.ts @@ -22,13 +22,14 @@ import { import { ScopeManager, SymbolTableReader } from "./scope"; import { SimpleVisitor } from "../parser/rd/visitor"; import { + GomDeferredType, GomFunctionType, GomListType, GomPrimitiveTypeOrAlias, GomStructType, GomTupleType, GomType, -} from "./type"; +} from "../types"; import { GomErrorManager } from "../util/error"; import { GomToken } from "../lexer/tokens"; import { GomModule } from "../parser/rd/modules"; @@ -62,13 +63,12 @@ export class SemanticAnalyzer extends SimpleVisitor { const module = new GomModule({ name: node.path.value }, this.errorManager); const semanticAnalyzer = new SemanticAnalyzer( module.parsed, - this.errorManager + this.errorManager, ); semanticAnalyzer.analyze(); - module.getAllExports().forEach((exp) => { if (exp instanceof NodeFunctionDefinition) { - this.scopeManager.putIdentifier(exp.name.value, exp, exp.resultantType); + this.scopeManager.putIdentifier(exp.name.value, exp, exp.gomType); } else if (exp instanceof NodeTypeDefinition) { this.scopeManager.putType(exp.name.token.value, exp); } else if (exp instanceof NodeLetStatement) { @@ -76,8 +76,8 @@ export class SemanticAnalyzer extends SimpleVisitor { this.scopeManager.putIdentifier( decl.lhs.token.value, decl.lhs, - decl.lhs.resultantType, - decl.rhs + decl.lhs.gomType, + decl.rhs, ); }); } @@ -127,19 +127,19 @@ export class SemanticAnalyzer extends SimpleVisitor { loc: arg.expectedType.loc, }); } - arg.resultantType = argType.gomType; + arg.gomType = argType.gomType; argTypes.push(argType.gomType); }); const fnType = new GomFunctionType(argTypes, returnType); - node.resultantType = fnType; + node.gomType = fnType; this.scopeManager.putIdentifier(node.name.value, node, fnType); this.scopeManager.beginScope(node.name.value); node.args.forEach((arg) => { this.scopeManager.putIdentifier( arg.name.token.value, arg.name, - arg.resultantType + arg.gomType, ); }); node.body.forEach((stmt) => this.visit(stmt)); @@ -154,7 +154,7 @@ export class SemanticAnalyzer extends SimpleVisitor { this.visit(node.conditionExpr); const typeResolver = new TypeResolver( this.scopeManager, - this.errorManager + this.errorManager, ); const conditionType = typeResolver.resolveType(node.conditionExpr); if (!conditionType?.isEqual(new GomPrimitiveTypeOrAlias("bool"))) { @@ -198,7 +198,7 @@ export class SemanticAnalyzer extends SimpleVisitor { if (decl.lhs instanceof NodeTerm) { const typeResolver = new TypeResolver( this.scopeManager, - this.errorManager + this.errorManager, ); const inferredType = typeResolver.resolveType(decl.rhs); if (!inferredType) { @@ -207,12 +207,12 @@ export class SemanticAnalyzer extends SimpleVisitor { loc: decl.rhs.loc, }); } - decl.lhs.resultantType = inferredType as GomPrimitiveTypeOrAlias; + decl.lhs.gomType = inferredType as GomPrimitiveTypeOrAlias; this.scopeManager.putIdentifier( decl.lhs.token.value, decl.lhs, inferredType, - decl.rhs + decl.rhs, ); } }); @@ -224,12 +224,12 @@ export class SemanticAnalyzer extends SimpleVisitor { this.visit(node.expr); const typeResolver = new TypeResolver( this.scopeManager, - this.errorManager + this.errorManager, ); returnType = typeResolver.resolveType(node.expr); } if (this.currentFunctionDefinition) { - const fnType = this.currentFunctionDefinition.resultantType; + const fnType = this.currentFunctionDefinition.gomType; if ( fnType instanceof GomFunctionType && returnType && @@ -275,11 +275,11 @@ class TypeResolver extends SimpleVisitor { constructor( scopeManager: ScopeManager, - private errorManager: GomErrorManager + private errorManager: GomErrorManager, ) { super(); this.symbolTableReader = new SymbolTableReader( - scopeManager.getCurrentSymbolTableNode() + scopeManager.getCurrentSymbolTableNode(), ); } @@ -290,7 +290,7 @@ class TypeResolver extends SimpleVisitor { visitStructInit(node: NodeStructInit): void { const structType = this.symbolTableReader.getType( - node.structTypeName.token.value + node.structTypeName.token.value, ); if (!structType) { this.errorManager.throwTypeError({ @@ -338,7 +338,7 @@ class TypeResolver extends SimpleVisitor { gomType.fields.set(fieldName.token.value, fieldType); } - node.resultantType = gomType; + node.gomType = gomType; this.currentType = gomType; } @@ -346,7 +346,7 @@ class TypeResolver extends SimpleVisitor { visitCollectionInit(node: NodeCollectionInit): void { // tuple or list const collectionType = this.symbolTableReader.getType( - node.collectionTypeName.token.value + node.collectionTypeName.token.value, ); if (!collectionType) { this.errorManager.throwTypeError({ @@ -376,7 +376,7 @@ class TypeResolver extends SimpleVisitor { } }); - node.resultantType = gomType; + node.gomType = gomType; this.currentType = gomType; } else if (gomType instanceof GomListType) { node.elements.forEach((element) => { @@ -390,7 +390,7 @@ class TypeResolver extends SimpleVisitor { } }); - node.resultantType = gomType; + node.gomType = gomType; this.currentType = gomType; } } @@ -407,50 +407,23 @@ class TypeResolver extends SimpleVisitor { const gomType = type.gomType; if (gomType instanceof GomStructType || gomType instanceof GomTupleType) { Array.from(gomType.fields.entries()).forEach(([key, field]) => { - const _field = field as GomPrimitiveTypeOrAlias; - if (_field.typeString.startsWith("resolve_type@@")) { - const idName = _field.toStr().replace("resolve_type@@", ""); - const id = this.symbolTableReader.getType(idName); - if (id) { - gomType.fields.set(key, id.gomType); - } else { - this.errorManager.throwTypeError({ - message: `Type ${idName} not found`, - loc: node.loc, - }); - } + if (field instanceof GomDeferredType) { + const resolvedType = this.resolveDeferredType(field, node.loc); + gomType.fields.set(key, resolvedType); } }); } else if (gomType instanceof GomListType) { - if (gomType.elementType instanceof GomPrimitiveTypeOrAlias) { - if (gomType.elementType.typeString.startsWith("resolve_type@@")) { - const idName = gomType.elementType.typeString.replace( - "resolve_type@@", - "" - ); - const id = this.symbolTableReader.getType(idName); - if (id) { - gomType.elementType = id.gomType; - } else { - this.errorManager.throwTypeError({ - message: `Type ${idName} not found`, - loc: node.loc, - }); - } - } + if (gomType.elementType instanceof GomDeferredType) { + const resolvedType = this.resolveDeferredType( + gomType.elementType, + node.loc, + ); + gomType.elementType = resolvedType; } } else if (gomType instanceof GomPrimitiveTypeOrAlias) { - if (gomType.typeString.startsWith("resolve_type@@")) { - const idName = gomType.typeString.replace("resolve_type@@", ""); - const id = this.symbolTableReader.getType(idName); - if (id) { - node.rhs.gomType = id.gomType; - } else { - this.errorManager.throwTypeError({ - message: `Type ${idName} not found`, - loc: node.loc, - }); - } + if (gomType instanceof GomDeferredType) { + const resolvedType = this.resolveDeferredType(gomType, node.loc); + node.rhs.gomType = resolvedType; } } } @@ -462,13 +435,13 @@ class TypeResolver extends SimpleVisitor { // ensure that node.lhs is a struct // only support member access for structs for now if (id.type instanceof GomStructType || id.type instanceof GomTupleType) { - node.lhs.resultantType = id.type; + node.lhs.gomType = id.type; if (node.rhs instanceof NodeTerm) { const structType = id.type; const field = structType.fields.get(node.rhs.token.value); if (field) { - node.rhs.resultantType = field; - node.resultantType = field; + node.rhs.gomType = field; + node.gomType = field; this.currentType = field; } else { this.errorManager.throwTypeError({ @@ -478,19 +451,19 @@ class TypeResolver extends SimpleVisitor { } } } else if (id.type instanceof GomListType) { - node.lhs.resultantType = id.type; + node.lhs.gomType = id.type; if ( node.rhs instanceof NodeTerm && GomListType.isBuiltInProperty(node.rhs.token.value) ) { const propertyType = GomListType.builtInPropertyType( - node.rhs.token.value + node.rhs.token.value, ); - node.rhs.resultantType = propertyType; - node.resultantType = propertyType; + node.rhs.gomType = propertyType; + node.gomType = propertyType; this.currentType = propertyType; } else { - node.resultantType = id.type.elementType; + node.gomType = id.type.elementType; this.currentType = id.type.elementType; } } else { @@ -542,12 +515,12 @@ class TypeResolver extends SimpleVisitor { if ( [GomToken.PLUS, GomToken.MINUS, GomToken.DIV, GomToken.MUL].includes( - node.op.type + node.op.type, ) ) { this.currentType = lhsType; if (lhsType) { - node.resultantType = this.currentType as GomPrimitiveTypeOrAlias; + node.gomType = this.currentType as GomPrimitiveTypeOrAlias; } } else if ( [ @@ -558,52 +531,50 @@ class TypeResolver extends SimpleVisitor { GomToken.GT, GomToken.GTE, ].includes( - node.op.type + node.op.type, // || [GomToken.AND, GomToken.OR].includes(node.op.type) ) ) { this.currentType = new GomPrimitiveTypeOrAlias("bool"); - node.resultantType = this.currentType as GomPrimitiveTypeOrAlias; + node.gomType = this.currentType as GomPrimitiveTypeOrAlias; } } visitCall(node: NodeCall): void { const fnName = (node.id as NodeTerm).token.value; const fn = this.symbolTableReader.getFunction(fnName); - if (fn && fn.node.resultantType instanceof GomFunctionType) { + if (fn && fn.node.gomType instanceof GomFunctionType) { const args = node.args.map((arg) => this.resolveType(arg)); - if (args.length !== fn.node.resultantType.args.length) { + if (args.length !== fn.node.gomType.args.length) { this.errorManager.throwTypeError({ message: `Argument count mismatch: expected ${ - fn.node.resultantType.args.length + fn.node.gomType.args.length }, got ${ args.length - } for function ${fnName} of type ${fn.node.resultantType.toStr()}`, + } for function ${fnName} of type ${fn.node.gomType.toStr()}`, loc: node.loc, }); } for (let i = 0; i < args.length; i++) { - if (!args[i]?.isEqual(fn.node.resultantType.args[i])) { + if (!args[i]?.isEqual(fn.node.gomType.args[i])) { this.errorManager.throwTypeError({ - message: `Type mismatch: expected ${ - fn.node.resultantType.args[i] - }, got ${ + message: `Type mismatch: expected ${fn.node.gomType.args[i]}, got ${ args[i] - } for argument ${i} of function ${fnName} of type ${fn.node.resultantType.toStr()}`, + } for argument ${i} of function ${fnName} of type ${fn.node.gomType.toStr()}`, loc: node.loc, }); } } - node.resultantType = fn.node.resultantType.returnType; - this.currentType = fn.node.resultantType.returnType; + node.gomType = fn.node.gomType.returnType; + this.currentType = fn.node.gomType.returnType; } else { if (fnName === "log") { // skip for now until modules are implemented node.args.map((arg) => this.resolveType(arg)); - node.resultantType = new GomPrimitiveTypeOrAlias("void"); - this.currentType = node.resultantType; + node.gomType = new GomPrimitiveTypeOrAlias("void"); + this.currentType = node.gomType; return; } else if (fnName === "push" || fnName === "pop") { // handle built-in free functions @@ -629,8 +600,8 @@ class TypeResolver extends SimpleVisitor { loc: node.loc, }); } - node.resultantType = new GomPrimitiveTypeOrAlias("void"); - this.currentType = node.resultantType; + node.gomType = new GomPrimitiveTypeOrAlias("void"); + this.currentType = node.gomType; return; } else if (fnName === "pop") { if (argTypes.length !== 1) { @@ -647,8 +618,8 @@ class TypeResolver extends SimpleVisitor { loc: node.loc, }); } - node.resultantType = argTypes[0].elementType; - this.currentType = node.resultantType; + node.gomType = argTypes[0].elementType; + this.currentType = node.gomType; return; } } @@ -665,29 +636,47 @@ class TypeResolver extends SimpleVisitor { return this.currentType!; }); - node.resultantType = new GomTupleType(elements); - this.currentType = node.resultantType; + node.gomType = new GomTupleType(elements); + this.currentType = node.gomType; } visitTerm(node: NodeTerm): void { const type = node.gomType; - if (type instanceof GomPrimitiveTypeOrAlias) { - if (type.typeString.startsWith("resolve_type@@")) { - const idName = type.typeString.replace("resolve_type@@", ""); - const id = this.symbolTableReader.getIdentifier(idName); - if (id && !id.isFunction()) { - node.resultantType = id.type; - this.currentType = id.type; - } else { - this.errorManager.throwTypeError({ - message: `Identifier ${idName} not found`, - loc: node.loc, - }); - } + if (type instanceof GomDeferredType) { + node.gomType = this.resolveDeferredType(type, node.loc); + this.currentType = node.gomType; + } else { + this.currentType = type; + } + } + + private resolveDeferredType( + deferredType: GomDeferredType, + loc: number, + ): GomType { + if (deferredType.marker === "resolve_type") { + const idName = deferredType.value; + const id = this.symbolTableReader.getIdentifier(idName); + if (id && !id.isFunction()) { + return id.type; + } else { + this.errorManager.throwTypeError({ + message: `Identifier ${idName} not found`, + loc: loc, + }); + } + } else if (deferredType.marker === "resolve_custom_type") { + const idName = deferredType.value; + const id = this.symbolTableReader.getType(idName); + if (id) { + return id.gomType; } else { - node.resultantType = type; - this.currentType = type; + this.errorManager.throwTypeError({ + message: `Type ${idName} not found`, + loc: loc, + }); } } + return deferredType; } } diff --git a/src/semantics/scope.ts b/src/semantics/scope.ts index f828bf7..38275f9 100644 --- a/src/semantics/scope.ts +++ b/src/semantics/scope.ts @@ -7,7 +7,7 @@ import { NodeTypeDefinition, } from "../parser/rd/nodes"; import { GomInternalError, SyntaxError } from "../util/error"; -import { GomPrimitiveTypeOrAliasValue, GomType } from "./type"; +import { GomPrimitiveTypeOrAliasValue, GomType } from "../types"; import { GOM_BUILT_IN_TYPES, GomToken } from "../lexer/tokens"; class SymbolTableNode { @@ -16,7 +16,7 @@ class SymbolTableNode { constructor( private name: string, private value: T, - private parent?: SymbolTableNode + private parent?: SymbolTableNode, ) {} addChild(value: SymbolTableNode) { @@ -93,7 +93,7 @@ class IdentifierEntry { name: string, node: NodeTerm | NodeFunctionDefinition, type: GomType, - valueExpr?: NodeExpr + valueExpr?: NodeExpr, ) { this.name = name; this.node = node; @@ -147,7 +147,7 @@ export class Scope { name: string, node: NodeTerm | NodeFunctionDefinition, type: GomType, - valueExpr?: NodeExpr + valueExpr?: NodeExpr, ) { const existingEntry = this.entries.types[name] ?? this.entries.identifiers[name]; @@ -162,7 +162,7 @@ export class Scope { name, node, type, - valueExpr + valueExpr, ); } @@ -196,7 +196,7 @@ export class Scope { getAllFunctions() { return Object.values(this.entries.identifiers).filter((entry) => - entry.isFunction() + entry.isFunction(), ); } } @@ -238,7 +238,7 @@ export class ScopeManager { const newSymbolTable = new SymbolTableNode( name, new Scope(), - this.currentSymbolTableNode + this.currentSymbolTableNode, ); this.currentSymbolTableNode.addChild(newSymbolTable); this.currentSymbolTableNode = newSymbolTable; @@ -271,7 +271,7 @@ export class ScopeManager { name: string, node: NodeTerm | NodeFunctionDefinition, type: GomType, - valueExpr?: NodeExpr + valueExpr?: NodeExpr, ) { this.getCurrentScope().putIdentifier(name, node, type, valueExpr); } diff --git a/src/semantics/type.ts b/src/types/index.ts similarity index 89% rename from src/semantics/type.ts rename to src/types/index.ts index 02c95ff..25c5f80 100644 --- a/src/semantics/type.ts +++ b/src/types/index.ts @@ -12,6 +12,7 @@ import assert from "node:assert"; export enum GomTypeKind { + Deferred = "Deferred", PrimitiveOrAlias = "PrimitiveOrAlias", Tuple = "Tuple", Struct = "Struct", @@ -229,3 +230,28 @@ export class GomFunctionType extends GomType { ); } } + +export type GomDeferredTypeMarker = + | "deferred" + | "resolve_type" + | "resolve_custom_type"; +export class GomDeferredType extends GomType { + kind: GomTypeKind; + marker: GomDeferredTypeMarker; + value: string; + + constructor(marker: GomDeferredTypeMarker, value: string) { + super(); + this.kind = GomTypeKind.Deferred; + this.marker = marker; + this.value = value; + } + + toStr(): string { + return `${this.marker}(${this.value})`; + } + + isEqual(_other: GomDeferredType): boolean { + throw new Error("GomDeferredType should not be compared directly"); + } +} diff --git a/src/types/type-attacher.ts b/src/types/type-attacher.ts new file mode 100644 index 0000000..4a1bdc0 --- /dev/null +++ b/src/types/type-attacher.ts @@ -0,0 +1,125 @@ +import { + GomDeferredType, + GomListType, + GomPrimitiveTypeOrAlias, + GomStructType, + GomTupleType, + GomType, +} from "."; +import { GOM_BUILT_IN_TYPES, GomToken } from "../lexer/tokens"; +import { + NodeCollectionInit, + NodeGomTypeComposite, + NodeGomTypeId, + NodeGomTypeList, + NodeGomTypeStruct, + NodeGomTypeStructField, + NodeGomTypeTuple, + NodeStructInit, + NodeTerm, + NodeTupleLiteral, + NodeTypeDefinition, +} from "../parser/rd/nodes"; +import { SimpleVisitor } from "../parser/rd/visitor"; + +export class TypeAttacher extends SimpleVisitor { + private getTermGomType(node: NodeTerm): GomType { + if (node.token.type === GomToken.IDENTIFIER) { + return new GomDeferredType("resolve_type", node.token.value); + } else if (node.token.type === GomToken.NUMLITERAL) { + return new GomPrimitiveTypeOrAlias("int"); + } else if (node.token.type === GomToken.STRLITERAL) { + return new GomPrimitiveTypeOrAlias("str"); + } else if ( + node.token.type === GomToken.TRUE || + node.token.type === GomToken.FALSE + ) { + return new GomPrimitiveTypeOrAlias("bool"); + } else if (node.token.type === GomToken.BUILT_IN_TYPE) { + return new GomPrimitiveTypeOrAlias(node.token.value); + } + + throw new Error(`Cannot determine type for token: ${node.token.type}`); + } + + visitTerm(node: NodeTerm): void { + const type = this.getTermGomType(node); + node.gomType = type; + } + + visitStructInit(node: NodeStructInit): void { + this.visitChildren(node); + node.gomType = new GomStructType( + node.structTypeName.token.value, + node.fields.reduce((acc, [field, expr]) => { + acc.set(field.token.value, expr.gomType); + return acc; + }, new Map()), + ); + } + + visitCollectionInit(node: NodeCollectionInit): void { + this.visitChildren(node); + node.gomType = new GomListType( + node.collectionTypeName.token.value, + node.elements[0].gomType, + ); + } + + visitTupleLiteral(node: NodeTupleLiteral): void { + this.visitChildren(node); + node.gomType = new GomTupleType( + node.elements.map((element) => element.gomType), + ); + } + + visitTypeDefinition(node: NodeTypeDefinition): void { + this.visitChildren(node); + node.gomType = node.rhs.gomType; + } + + visitGomTypeStruct(node: NodeGomTypeStruct): void { + this.visitChildren(node); + node.gomType = new GomStructType( + node.name.token.value, + node.fields.reduce((acc, field) => { + acc.set(field.name.value, field.fieldType.gomType); + return acc; + }, new Map()), + ); + } + + visitGomTypeList(node: NodeGomTypeList): void { + this.visitChildren(node); + node.gomType = new GomListType( + node.name.token.value, + node.elementType.gomType, + ); + } + + visitGomTypeTuple(node: NodeGomTypeTuple): void { + this.visitChildren(node); + node.gomType = new GomTupleType(node.fields.map((field) => field.gomType)); + } + + visitGomTypeComposite(node: NodeGomTypeComposite): void { + this.visitChildren(node); + node.gomType = new GomListType(node.id.token.value, node.fields[0].gomType); + } + + visitGomTypeStructField(node: NodeGomTypeStructField): void { + this.visitChildren(node); + node.gomType = node.fieldType.gomType; + } + + visitGomTypeId(node: NodeGomTypeId): void { + if (GOM_BUILT_IN_TYPES.has(node.id.token.value)) { + node.gomType = new GomPrimitiveTypeOrAlias(node.id.token.value); + } else { + node.gomType = new GomDeferredType( + "resolve_custom_type", + node.id.token.value, + ); + } + } +} diff --git a/src/util/console.ts b/src/util/console.ts new file mode 100644 index 0000000..359b93e --- /dev/null +++ b/src/util/console.ts @@ -0,0 +1,11 @@ +export const logGreen = (message: string) => { + console.log(`\x1b[102m DONE \x1b[0m ${message}`); +}; + +export const logBlue = (message: string) => { + console.log(`\x1b[106m INFO \x1b[0m ${message}`); +}; + +export const logRed = (message: string) => { + console.log(`\x1b[101m ERROR \x1b[0m ${message}`); +}; diff --git a/src/util/error.ts b/src/util/error.ts index 8213502..c439790 100644 --- a/src/util/error.ts +++ b/src/util/error.ts @@ -1,23 +1,36 @@ import chalk from "chalk"; -export class SyntaxError extends Error { +export abstract class GomError { + name: string = "GomError"; + message: string = ""; + + print() { + console.error(this.message); + } +} + +export class SyntaxError extends GomError { constructor({ loc, message }: { loc: [number, number]; message: string }) { - super( - chalk.bold(`${chalk.red(`SyntaxError at ${loc.join(":")}`)}: ${message}`) - ); + super(); + this.message = + chalk.bold(chalk.red(`SyntaxError at ${loc.join(":")}`)) + `: ${message}`; + this.name = "GomSyntaxError"; } } -export class TypeError extends Error { +export class TypeError extends GomError { constructor({ message, loc }: { message: string; loc: [number, number] }) { - super(`TypeError at ${loc.join(":")}: ${message}`); + super(); + this.message = + chalk.bold(chalk.red(`TypeError at ${loc.join(":")}`)) + `: ${message}`; this.name = "GomTypeError"; } } -export class GomInternalError extends Error { +export class GomInternalError extends GomError { constructor({ message }: { message: string }) { - super(`GomInternalError: ${message}`); + super(); + this.message = chalk.bold(chalk.red(`GomInternalError`)) + `: ${message}`; this.name = "GomInternalError"; } } @@ -46,17 +59,25 @@ export class GomErrorManager { const { line, column } = this.getLineAndColumn(loc); const lines = this.src.split("\n"); const errorLine = lines[line - 1]; - return `${line} | ${errorLine}\n${" ".repeat(column)}^`; + const lineNum = line.toString().padStart(4, " "); + const caretPadding = " ".repeat(lineNum.length + 2 + column - 1); + return `\n${lineNum} | ${errorLine.trim()}\n${caretPadding}↑`; } throwSyntaxError({ loc, message }: { loc: number; message: string }): never { const { line, column } = this.getLineAndColumn(loc); - throw new SyntaxError({ loc: [line, column], message }); + throw new SyntaxError({ + loc: [line, column], + message: `${message}\n${this.getErrorSrcMessage(loc)}`, + }); } throwTypeError({ loc, message }: { loc: number; message: string }): never { const { line, column } = this.getLineAndColumn(loc); - throw new TypeError({ loc: [line, column], message }); + throw new TypeError({ + loc: [line, column], + message: `${message}\n${this.getErrorSrcMessage(loc)}`, + }); } throwInternalError(message: string): never { diff --git a/test_compile.sh b/test_compile.sh new file mode 100755 index 0000000..14a5ec3 --- /dev/null +++ b/test_compile.sh @@ -0,0 +1,5 @@ +# for .gom files in examples directory +for file in examples/*.gom; do + echo "Compiling $file" + npm run compile examples/"$(basename "$file")" llvm +done \ No newline at end of file diff --git a/tree.json b/tree.json index 54310cf..44de125 100644 --- a/tree.json +++ b/tree.json @@ -1,12 +1,22 @@ { - "_id": 131, + "_id": 100, "type": "PROGRAM", "loc": 0, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "importDeclarations": [ { "_id": 0, "type": "IMPORT_DECLARATION", "loc": 7, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "path": { "type": "identifier", "value": "io", @@ -17,1932 +27,1359 @@ ], "typeDefinitions": [ { - "_id": 5, + "_id": 7, "type": "TYPE_DEFINITION", - "loc": 12, + "loc": 21, + "gomType": { + "kind": "Tuple", + "fields": {} + }, "name": { "_id": 1, "type": "TERM", - "loc": 17, - "token": { - "type": "identifier", - "value": "Numbers", - "start": 17, - "end": 23 - }, + "loc": 26, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@Numbers" + "kind": "Deferred", + "marker": "resolve_type", + "value": "HttpResponse" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@Numbers" + "token": { + "type": "identifier", + "value": "HttpResponse", + "start": 26, + "end": 37 } }, "rhs": { - "_id": 4, - "type": "GOM_TYPE_LIST", - "loc": 27, - "elementType": { - "_id": 3, - "type": "GOM_TYPE_ID", - "loc": 28, - "id": { - "_id": 2, - "type": "TERM", - "loc": 28, - "token": { - "type": "built_in_type", - "value": "int", - "start": 28, - "end": 30 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "gomType": { - "kind": "List", - "name": "Numbers", - "elementType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - } - } - }, - { - "_id": 17, - "type": "TYPE_DEFINITION", - "loc": 35, - "name": { "_id": 6, - "type": "TERM", - "loc": 40, - "token": { - "type": "identifier", - "value": "Temperature", - "start": 40, - "end": 50 - }, + "type": "GOM_TYPE_TUPLE", + "loc": 41, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@Temperature" + "kind": "Tuple", + "fields": {} }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@Temperature" - } - }, - "rhs": { - "_id": 16, - "type": "GOM_TYPE_STRUCT", - "loc": 54, "fields": [ { - "_id": 9, - "type": "GOM_TYPE_STRUCT_FIELD", - "loc": 57, - "name": { - "type": "identifier", - "value": "high", - "start": 57, - "end": 60 + "_id": 3, + "type": "GOM_TYPE_ID", + "loc": 43, + "gomType": { + "kind": "PrimitiveOrAlias", + "typeString": "int" }, - "fieldType": { - "_id": 8, - "type": "GOM_TYPE_ID", - "loc": 63, - "id": { - "_id": 7, - "type": "TERM", - "loc": 63, - "token": { - "type": "built_in_type", - "value": "int", - "start": 63, - "end": 65 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, + "id": { + "_id": 2, + "type": "TERM", + "loc": 43, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - } - }, - { - "_id": 12, - "type": "GOM_TYPE_STRUCT_FIELD", - "loc": 69, - "name": { - "type": "identifier", - "value": "low", - "start": 69, - "end": 71 - }, - "fieldType": { - "_id": 11, - "type": "GOM_TYPE_ID", - "loc": 74, - "id": { - "_id": 10, - "type": "TERM", - "loc": 74, - "token": { - "type": "built_in_type", - "value": "int", - "start": 74, - "end": 76 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "token": { + "type": "built_in_type", + "value": "int", + "start": 43, + "end": 45 } } }, { - "_id": 15, - "type": "GOM_TYPE_STRUCT_FIELD", - "loc": 80, - "name": { - "type": "identifier", - "value": "avg", - "start": 80, - "end": 82 + "_id": 5, + "type": "GOM_TYPE_ID", + "loc": 48, + "gomType": { + "kind": "PrimitiveOrAlias", + "typeString": "bool" }, - "fieldType": { - "_id": 14, - "type": "GOM_TYPE_ID", - "loc": 85, - "id": { - "_id": 13, - "type": "TERM", - "loc": 85, - "token": { - "type": "built_in_type", - "value": "int", - "start": 85, - "end": 87 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, + "id": { + "_id": 4, + "type": "TERM", + "loc": 48, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "token": { + "type": "built_in_type", + "value": "bool", + "start": 48, + "end": 51 } } } - ], - "gomType": { - "kind": "Struct", - "name": "Temperature", - "fields": {} - } + ] } } ], "globalVariables": [], - "functionDeclarations": [], - "exportStatements": [], - "mainFunction": { - "_id": 130, - "type": "MAIN_FUNCTION", - "loc": 102, - "body": [ - { - "_id": 21, - "type": "LET_STATEMENT", - "loc": 112, - "decls": [ + "functionDeclarations": [ + { + "_id": 27, + "type": "FUNCTION_DEFINITION", + "loc": 58, + "gomType": { + "kind": "Function", + "args": [ { - "_id": 20, - "type": "ASSIGNMENT", - "loc": 116, - "lhs": { - "_id": 18, - "type": "TERM", - "loc": 116, - "token": { - "type": "identifier", - "value": "a", - "start": 116, - "end": 116 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@a" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "rhs": { - "_id": 19, - "type": "TERM", - "loc": 120, - "token": { - "type": "numliteral", - "value": "1", - "start": 120, - "end": 120 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" } - ] + ], + "returnType": { + "kind": "Tuple", + "fields": {} + } }, - { - "_id": 28, - "type": "EXPRESSION_STATEMENT", - "loc": 148, - "expr": { - "_id": 27, - "type": "ACCESS", - "loc": 148, - "lhs": { - "_id": 22, + "name": { + "type": "identifier", + "value": "process_http", + "start": 67, + "end": 78 + }, + "args": [ + { + "_id": 10, + "type": "ARGUMENT_ITEM", + "loc": 80, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "name": { + "_id": 8, "type": "TERM", - "loc": 148, + "loc": 80, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "token": { "type": "identifier", - "value": "io", - "start": 148, - "end": 149 + "value": "url", + "start": 80, + "end": 82 + } + }, + "expectedType": { + "_id": 9, + "type": "TERM", + "loc": 85, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, + "token": { + "type": "built_in_type", + "value": "str", + "start": 85, + "end": 87 + } + } + } + ], + "returnType": { + "_id": 13, + "type": "FUNCTION_RETURN_TYPE", + "loc": 89, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "returnType": { + "_id": 12, + "type": "GOM_TYPE_ID", + "loc": 91, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "id": { + "_id": 11, + "type": "TERM", + "loc": 91, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" + "token": { + "type": "identifier", + "value": "HttpResponse", + "start": 91, + "end": 102 } + } + } + }, + "body": [ + { + "_id": 22, + "type": "IF_STATEMENT", + "loc": 108, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "rhs": { - "_id": 26, - "type": "CALL", - "loc": 151, - "id": { - "_id": 23, - "type": "TERM", - "loc": 151, - "token": { - "type": "identifier", - "value": "log", - "start": 151, - "end": 153 - }, + "conditionExpr": { + "_id": 17, + "type": "EXPR_BRACKETED", + "loc": 110, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "expr": { + "_id": 16, + "type": "COMPARISON", + "loc": 111, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" - } - }, - "args": [ - { - "_id": 24, + "lhs": { + "_id": 14, "type": "TERM", - "loc": 155, - "token": { - "type": "strliteral", - "value": "\"a: \"", - "start": 155, - "end": 159 - }, + "loc": 111, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" + "token": { + "type": "identifier", + "value": "url", + "start": 111, + "end": 113 } }, - { - "_id": 25, + "op": { + "type": "==", + "value": "==", + "start": 115, + "end": 116 + }, + "rhs": { + "_id": 15, "type": "TERM", - "loc": 162, - "token": { - "type": "identifier", - "value": "a", - "start": 162, - "end": 162 - }, + "loc": 118, "gomType": { "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@a" + "typeString": "str" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "token": { + "type": "strliteral", + "value": "\"http://www.example.com\"", + "start": 118, + "end": 141 } } - ], - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" } }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } - } - }, - { - "_id": 39, - "type": "LET_STATEMENT", - "loc": 168, - "decls": [ - { - "_id": 38, - "type": "ASSIGNMENT", - "loc": 172, - "lhs": { - "_id": 29, - "type": "TERM", - "loc": 172, - "token": { - "type": "identifier", - "value": "temperature", - "start": 172, - "end": 182 - }, + "body": [ + { + "_id": 21, + "type": "RETURN_STATEMENT", + "loc": 150, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@temperature" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "Struct", - "name": "Temperature", - "fields": {} - } - }, - "rhs": { - "_id": 37, - "type": "STRUCT_INIT", - "loc": 186, - "structTypeName": { - "_id": 30, - "type": "TERM", - "loc": 186, - "token": { - "type": "identifier", - "value": "Temperature", - "start": 186, - "end": 196 - }, + "expr": { + "_id": 20, + "type": "TUPLE_LITERAL", + "loc": 157, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@Temperature" + "kind": "Tuple", + "fields": {} }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@Temperature" - } - }, - "fields": [ - [ - { - "_id": 31, - "type": "TERM", - "loc": 202, - "token": { - "type": "identifier", - "value": "high", - "start": 202, - "end": 205 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@high" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@high" - } - }, + "elements": [ { - "_id": 32, + "_id": 18, "type": "TERM", - "loc": 208, - "token": { - "type": "numliteral", - "value": "32", - "start": 208, - "end": 209 - }, + "loc": 159, "gomType": { "kind": "PrimitiveOrAlias", "typeString": "int" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - } - ], - [ - { - "_id": 33, - "type": "TERM", - "loc": 214, - "token": { - "type": "identifier", - "value": "low", - "start": 214, - "end": 216 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@low" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@low" - } - }, - { - "_id": 34, - "type": "TERM", - "loc": 219, "token": { "type": "numliteral", - "value": "26", - "start": 219, - "end": 220 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - } - ], - [ - { - "_id": 35, - "type": "TERM", - "loc": 225, - "token": { - "type": "identifier", - "value": "avg", - "start": 225, - "end": 227 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@avg" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@avg" + "value": "200", + "start": 159, + "end": 161 } }, { - "_id": 36, + "_id": 19, "type": "TERM", - "loc": 230, - "token": { - "type": "numliteral", - "value": "29", - "start": 230, - "end": 231 - }, + "loc": 164, "gomType": { "kind": "PrimitiveOrAlias", - "typeString": "int" + "typeString": "bool" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "token": { + "type": "true", + "value": "true", + "start": 164, + "end": 167 } } ] - ], - "resultantType": { - "kind": "Struct", - "name": "Temperature", - "fields": {} } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" } + ] + }, + { + "_id": 26, + "type": "RETURN_STATEMENT", + "loc": 181, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "expr": { + "_id": 25, + "type": "TUPLE_LITERAL", + "loc": 188, + "gomType": { + "kind": "Tuple", + "fields": {} + }, + "elements": [ + { + "_id": 23, + "type": "TERM", + "loc": 190, + "gomType": { + "kind": "PrimitiveOrAlias", + "typeString": "int" + }, + "token": { + "type": "numliteral", + "value": "401", + "start": 190, + "end": 192 + } + }, + { + "_id": 24, + "type": "TERM", + "loc": 195, + "gomType": { + "kind": "PrimitiveOrAlias", + "typeString": "bool" + }, + "token": { + "type": "false", + "value": "false", + "start": 195, + "end": 199 + } + } + ] } - ] + } + ] + }, + { + "_id": 78, + "type": "FUNCTION_DEFINITION", + "loc": 207, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - { - "_id": 48, - "type": "EXPRESSION_STATEMENT", - "loc": 239, - "expr": { - "_id": 47, - "type": "ACCESS", - "loc": 239, - "lhs": { - "_id": 40, + "name": { + "type": "identifier", + "value": "process_http_retry", + "start": 216, + "end": 233 + }, + "args": [ + { + "_id": 30, + "type": "ARGUMENT_ITEM", + "loc": 235, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "name": { + "_id": 28, "type": "TERM", - "loc": 239, + "loc": 235, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "token": { "type": "identifier", - "value": "io", - "start": 239, - "end": 240 + "value": "url", + "start": 235, + "end": 237 + } + }, + "expectedType": { + "_id": 29, + "type": "TERM", + "loc": 240, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, + "token": { + "type": "built_in_type", + "value": "str", + "start": 240, + "end": 242 + } + } + }, + { + "_id": 33, + "type": "ARGUMENT_ITEM", + "loc": 245, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "name": { + "_id": 31, + "type": "TERM", + "loc": 245, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" + "token": { + "type": "identifier", + "value": "retries", + "start": 245, + "end": 251 } }, - "rhs": { - "_id": 46, - "type": "CALL", - "loc": 242, - "id": { - "_id": 41, - "type": "TERM", - "loc": 242, - "token": { - "type": "identifier", - "value": "log", - "start": 242, - "end": 244 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" - } + "expectedType": { + "_id": 32, + "type": "TERM", + "loc": 254, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "args": [ + "token": { + "type": "built_in_type", + "value": "int", + "start": 254, + "end": 256 + } + } + } + ], + "returnType": { + "_id": 36, + "type": "FUNCTION_RETURN_TYPE", + "loc": 258, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "returnType": { + "_id": 35, + "type": "GOM_TYPE_ID", + "loc": 260, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "id": { + "_id": 34, + "type": "TERM", + "loc": 260, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "token": { + "type": "identifier", + "value": "HttpResponse", + "start": 260, + "end": 271 + } + } + } + }, + "body": [ + { + "_id": 73, + "type": "FOR_STATEMENT", + "loc": 277, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "initExpr": { + "_id": 40, + "type": "LET_STATEMENT", + "loc": 282, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "decls": [ { - "_id": 42, - "type": "TERM", - "loc": 246, - "token": { - "type": "strliteral", - "value": "\"Average temperature: \"", - "start": 246, - "end": 268 - }, + "_id": 39, + "type": "ASSIGNMENT", + "loc": 286, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" - } - }, - { - "_id": 45, - "type": "ACCESS", - "loc": 271, "lhs": { - "_id": 43, + "_id": 37, "type": "TERM", - "loc": 271, - "token": { - "type": "identifier", - "value": "temperature", - "start": 271, - "end": 281 - }, + "loc": 286, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@temperature" + "kind": "Deferred", + "marker": "resolve_type", + "value": "i" }, - "resultantType": { - "kind": "Struct", - "name": "Temperature", - "fields": {} + "token": { + "type": "identifier", + "value": "i", + "start": 286, + "end": 286 } }, "rhs": { - "_id": 44, + "_id": 38, "type": "TERM", - "loc": 283, - "token": { - "type": "identifier", - "value": "avg", - "start": 283, - "end": 285 - }, + "loc": 290, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@avg" + "kind": "Deferred", + "marker": "resolve_type", + "value": "retries" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "token": { + "type": "identifier", + "value": "retries", + "start": 290, + "end": 296 } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" } } - ], - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } + ] }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } - } - }, - { - "_id": 58, - "type": "LET_STATEMENT", - "loc": 291, - "decls": [ - { - "_id": 57, - "type": "ASSIGNMENT", - "loc": 295, + "conditionExpr": { + "_id": 43, + "type": "COMPARISON", + "loc": 299, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "lhs": { - "_id": 49, + "_id": 41, "type": "TERM", - "loc": 295, + "loc": 299, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "i" + }, "token": { "type": "identifier", - "value": "numbers", - "start": 295, - "end": 301 - }, + "value": "i", + "start": 299, + "end": 299 + } + }, + "op": { + "type": ">", + "value": ">", + "start": 301, + "end": 301 + }, + "rhs": { + "_id": 42, + "type": "TERM", + "loc": 303, "gomType": { "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@numbers" + "typeString": "int" }, - "resultantType": { - "kind": "List", - "name": "Numbers", - "elementType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } + "token": { + "type": "numliteral", + "value": "0", + "start": 303, + "end": 303 + } + } + }, + "updateExpr": { + "_id": 48, + "type": "ASSIGNMENT", + "loc": 306, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "lhs": { + "_id": 44, + "type": "TERM", + "loc": 306, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "i" + }, + "token": { + "type": "identifier", + "value": "i", + "start": 306, + "end": 306 } }, "rhs": { - "_id": 56, - "type": "COLLECTION_INIT", - "loc": 305, - "collectionTypeName": { - "_id": 50, + "_id": 47, + "type": "SUM", + "loc": 310, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "lhs": { + "_id": 45, "type": "TERM", - "loc": 305, + "loc": 310, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "i" + }, "token": { "type": "identifier", - "value": "Numbers", - "start": 305, - "end": 311 - }, + "value": "i", + "start": 310, + "end": 310 + } + }, + "op": { + "type": "-", + "value": "-", + "start": 312, + "end": 312 + }, + "rhs": { + "_id": 46, + "type": "TERM", + "loc": 314, "gomType": { "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@Numbers" + "typeString": "int" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@Numbers" - } - }, - "elements": [ - { - "_id": 51, - "type": "TERM", - "loc": 315, - "token": { - "type": "numliteral", - "value": "1", - "start": 315, - "end": 315 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - { - "_id": 52, - "type": "TERM", - "loc": 318, - "token": { - "type": "numliteral", - "value": "2", - "start": 318, - "end": 318 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - { - "_id": 53, - "type": "TERM", - "loc": 321, - "token": { - "type": "numliteral", - "value": "3", - "start": 321, - "end": 321 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - { - "_id": 54, - "type": "TERM", - "loc": 324, - "token": { - "type": "numliteral", - "value": "4", - "start": 324, - "end": 324 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - { - "_id": 55, - "type": "TERM", - "loc": 327, - "token": { - "type": "numliteral", - "value": "5", - "start": 327, - "end": 327 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - } - ], - "resultantType": { - "kind": "List", - "name": "Numbers", - "elementType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "token": { + "type": "numliteral", + "value": "1", + "start": 314, + "end": 314 } } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" } - } - ] - }, - { - "_id": 84, - "type": "FOR_STATEMENT", - "loc": 333, - "initExpr": { - "_id": 62, - "type": "LET_STATEMENT", - "loc": 338, - "decls": [ - { - "_id": 61, - "type": "ASSIGNMENT", - "loc": 342, - "lhs": { - "_id": 59, - "type": "TERM", - "loc": 342, - "token": { - "type": "identifier", - "value": "i", - "start": 342, - "end": 342 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@i" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "rhs": { - "_id": 60, - "type": "TERM", - "loc": 346, - "token": { - "type": "numliteral", - "value": "0", - "start": 346, - "end": 346 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } - } - ] - }, - "conditionExpr": { - "_id": 67, - "type": "COMPARISON", - "loc": 349, - "lhs": { - "_id": 63, - "type": "TERM", - "loc": 349, - "token": { - "type": "identifier", - "value": "i", - "start": 349, - "end": 349 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@i" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "op": { - "type": "<", - "value": "<", - "start": 351, - "end": 351 }, - "rhs": { - "_id": 66, - "type": "ACCESS", - "loc": 353, - "lhs": { - "_id": 64, - "type": "TERM", - "loc": 353, - "token": { - "type": "identifier", - "value": "numbers", - "start": 353, - "end": 359 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@numbers" - }, - "resultantType": { - "kind": "List", - "name": "Numbers", - "elementType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - } - }, - "rhs": { - "_id": 65, - "type": "TERM", - "loc": 361, - "token": { - "type": "identifier", - "value": "length", - "start": 361, - "end": 366 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@length" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "bool" - } - }, - "updateExpr": { - "_id": 72, - "type": "ASSIGNMENT", - "loc": 369, - "lhs": { - "_id": 68, - "type": "TERM", - "loc": 369, - "token": { - "type": "identifier", - "value": "i", - "start": 369, - "end": 369 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@i" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@i" - } - }, - "rhs": { - "_id": 71, - "type": "SUM", - "loc": 373, - "lhs": { - "_id": 69, - "type": "TERM", - "loc": 373, - "token": { - "type": "identifier", - "value": "i", - "start": 373, - "end": 373 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@i" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "op": { - "type": "+", - "value": "+", - "start": 375, - "end": 375 - }, - "rhs": { - "_id": 70, - "type": "TERM", - "loc": 377, - "token": { - "type": "numliteral", - "value": "1", - "start": 377, - "end": 377 - }, + "body": [ + { + "_id": 59, + "type": "EXPRESSION_STATEMENT", + "loc": 323, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } - }, - "body": [ - { - "_id": 83, - "type": "EXPRESSION_STATEMENT", - "loc": 384, - "expr": { - "_id": 82, - "type": "ACCESS", - "loc": 384, - "lhs": { - "_id": 73, - "type": "TERM", - "loc": 384, - "token": { - "type": "identifier", - "value": "io", - "start": 384, - "end": 385 - }, + "expr": { + "_id": 58, + "type": "ACCESS", + "loc": 323, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" - } - }, - "rhs": { - "_id": 81, - "type": "CALL", - "loc": 387, - "id": { - "_id": 74, + "lhs": { + "_id": 49, "type": "TERM", - "loc": 387, - "token": { - "type": "identifier", - "value": "log", - "start": 387, - "end": 389 - }, + "loc": 323, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" + "kind": "Deferred", + "marker": "resolve_type", + "value": "io" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" + "token": { + "type": "identifier", + "value": "io", + "start": 323, + "end": 324 } }, - "args": [ - { - "_id": 75, - "type": "TERM", - "loc": 391, - "token": { - "type": "strliteral", - "value": "\"Number at index \"", - "start": 391, - "end": 408 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" - } + "rhs": { + "_id": 57, + "type": "CALL", + "loc": 326, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - { - "_id": 76, + "id": { + "_id": 50, "type": "TERM", - "loc": 411, - "token": { - "type": "identifier", - "value": "i", - "start": 411, - "end": 411 - }, + "loc": 326, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@i" + "kind": "Deferred", + "marker": "resolve_type", + "value": "log" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - { - "_id": 77, - "type": "TERM", - "loc": 414, "token": { - "type": "strliteral", - "value": "\" is \"", - "start": 414, - "end": 419 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" + "type": "identifier", + "value": "log", + "start": 326, + "end": 328 } }, - { - "_id": 80, - "type": "ACCESS", - "loc": 422, - "lhs": { - "_id": 78, + "args": [ + { + "_id": 51, "type": "TERM", - "loc": 422, - "token": { - "type": "identifier", - "value": "numbers", - "start": 422, - "end": 428 - }, + "loc": 330, "gomType": { "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@numbers" + "typeString": "str" }, - "resultantType": { - "kind": "List", - "name": "Numbers", - "elementType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } + "token": { + "type": "strliteral", + "value": "\"Round: \"", + "start": 330, + "end": 338 } }, - "rhs": { - "_id": 79, - "type": "TERM", - "loc": 430, - "token": { - "type": "identifier", - "value": "i", - "start": 430, - "end": 430 - }, + { + "_id": 56, + "type": "SUM", + "loc": 341, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@i" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@i" + "lhs": { + "_id": 54, + "type": "SUM", + "loc": 341, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "lhs": { + "_id": 52, + "type": "TERM", + "loc": 341, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "retries" + }, + "token": { + "type": "identifier", + "value": "retries", + "start": 341, + "end": 347 + } + }, + "op": { + "type": "-", + "value": "-", + "start": 349, + "end": 349 + }, + "rhs": { + "_id": 53, + "type": "TERM", + "loc": 351, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "i" + }, + "token": { + "type": "identifier", + "value": "i", + "start": 351, + "end": 351 + } + } + }, + "op": { + "type": "+", + "value": "+", + "start": 353, + "end": 353 + }, + "rhs": { + "_id": 55, + "type": "TERM", + "loc": 355, + "gomType": { + "kind": "PrimitiveOrAlias", + "typeString": "int" + }, + "token": { + "type": "numliteral", + "value": "1", + "start": 355, + "end": 355 + } } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" } - } - ], - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" + ] } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" } - } - } - ] - }, - { - "_id": 93, - "type": "EXPRESSION_STATEMENT", - "loc": 440, - "expr": { - "_id": 92, - "type": "ACCESS", - "loc": 440, - "lhs": { - "_id": 85, - "type": "TERM", - "loc": 440, - "token": { - "type": "identifier", - "value": "io", - "start": 440, - "end": 441 }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" - } - }, - "rhs": { - "_id": 91, - "type": "CALL", - "loc": 443, - "id": { - "_id": 86, - "type": "TERM", - "loc": 443, - "token": { - "type": "identifier", - "value": "log", - "start": 443, - "end": 445 - }, + { + "_id": 65, + "type": "LET_STATEMENT", + "loc": 363, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" - } - }, - "args": [ - { - "_id": 87, - "type": "TERM", - "loc": 447, - "token": { - "type": "strliteral", - "value": "\"Numbers length: \"", - "start": 447, - "end": 464 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" - } - }, - { - "_id": 90, - "type": "ACCESS", - "loc": 467, - "lhs": { - "_id": 88, - "type": "TERM", - "loc": 467, - "token": { - "type": "identifier", - "value": "numbers", - "start": 467, - "end": 473 - }, + "decls": [ + { + "_id": 64, + "type": "ASSIGNMENT", + "loc": 367, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@numbers" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "List", - "name": "Numbers", - "elementType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "lhs": { + "_id": 60, + "type": "TERM", + "loc": 367, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "resp" + }, + "token": { + "type": "identifier", + "value": "resp", + "start": 367, + "end": 370 } - } - }, - "rhs": { - "_id": 89, - "type": "TERM", - "loc": 475, - "token": { - "type": "identifier", - "value": "length", - "start": 475, - "end": 480 }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@length" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "rhs": { + "_id": 63, + "type": "CALL", + "loc": 374, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "id": { + "_id": 61, + "type": "TERM", + "loc": 374, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "process_http" + }, + "token": { + "type": "identifier", + "value": "process_http", + "start": 374, + "end": 385 + } + }, + "args": [ + { + "_id": 62, + "type": "TERM", + "loc": 387, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "url" + }, + "token": { + "type": "identifier", + "value": "url", + "start": 387, + "end": 389 + } + } + ] } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" } - } - ], - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } - } - }, - { - "_id": 98, - "type": "EXPRESSION_STATEMENT", - "loc": 518, - "expr": { - "_id": 97, - "type": "CALL", - "loc": 518, - "id": { - "_id": 94, - "type": "TERM", - "loc": 518, - "token": { - "type": "identifier", - "value": "push", - "start": 518, - "end": 521 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@push" + ] }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@push" - } - }, - "args": [ { - "_id": 95, - "type": "TERM", - "loc": 523, - "token": { - "type": "identifier", - "value": "numbers", - "start": 523, - "end": 529 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@numbers" - }, - "resultantType": { - "kind": "List", - "name": "Numbers", - "elementType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - } - }, - { - "_id": 96, - "type": "TERM", - "loc": 532, - "token": { - "type": "numliteral", - "value": "6", - "start": 532, - "end": 532 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - } - ], - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } - } - }, - { - "_id": 107, - "type": "EXPRESSION_STATEMENT", - "loc": 537, - "expr": { - "_id": 106, - "type": "ACCESS", - "loc": 537, - "lhs": { - "_id": 99, - "type": "TERM", - "loc": 537, - "token": { - "type": "identifier", - "value": "io", - "start": 537, - "end": 538 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" - } - }, - "rhs": { - "_id": 105, - "type": "CALL", - "loc": 540, - "id": { - "_id": 100, - "type": "TERM", - "loc": 540, - "token": { - "type": "identifier", - "value": "log", - "start": 540, - "end": 542 - }, + "_id": 72, + "type": "IF_STATEMENT", + "loc": 397, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" - } - }, - "args": [ - { - "_id": 101, - "type": "TERM", - "loc": 544, - "token": { - "type": "strliteral", - "value": "\"After push: \"", - "start": 544, - "end": 557 - }, + "conditionExpr": { + "_id": 69, + "type": "EXPR_BRACKETED", + "loc": 399, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" - } - }, - { - "_id": 104, - "type": "ACCESS", - "loc": 560, - "lhs": { - "_id": 102, - "type": "TERM", - "loc": 560, - "token": { - "type": "identifier", - "value": "numbers", - "start": 560, - "end": 566 - }, + "expr": { + "_id": 68, + "type": "ACCESS", + "loc": 400, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@numbers" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "List", - "name": "Numbers", - "elementType": { + "lhs": { + "_id": 66, + "type": "TERM", + "loc": 400, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "resp" + }, + "token": { + "type": "identifier", + "value": "resp", + "start": 400, + "end": 403 + } + }, + "rhs": { + "_id": 67, + "type": "TERM", + "loc": 405, + "gomType": { "kind": "PrimitiveOrAlias", "typeString": "int" + }, + "token": { + "type": "numliteral", + "value": "1", + "start": 405, + "end": 405 } } - }, - "rhs": { - "_id": 103, - "type": "TERM", - "loc": 568, - "token": { - "type": "identifier", - "value": "length", - "start": 568, - "end": 573 - }, + } + }, + "body": [ + { + "_id": 71, + "type": "RETURN_STATEMENT", + "loc": 416, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@length" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "expr": { + "_id": 70, + "type": "TERM", + "loc": 423, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "resp" + }, + "token": { + "type": "identifier", + "value": "resp", + "start": 423, + "end": 426 + } } - }, - "resultantType": { + } + ] + } + ] + }, + { + "_id": 77, + "type": "RETURN_STATEMENT", + "loc": 442, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "expr": { + "_id": 76, + "type": "TUPLE_LITERAL", + "loc": 449, + "gomType": { + "kind": "Tuple", + "fields": {} + }, + "elements": [ + { + "_id": 74, + "type": "TERM", + "loc": 451, + "gomType": { "kind": "PrimitiveOrAlias", "typeString": "int" + }, + "token": { + "type": "numliteral", + "value": "500", + "start": 451, + "end": 453 + } + }, + { + "_id": 75, + "type": "TERM", + "loc": 456, + "gomType": { + "kind": "PrimitiveOrAlias", + "typeString": "bool" + }, + "token": { + "type": "false", + "value": "false", + "start": 456, + "end": 460 } } - ], - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" + ] } } - }, + ] + } + ], + "exportStatements": [], + "mainFunction": { + "_id": 99, + "type": "MAIN_FUNCTION", + "loc": 477, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, + "body": [ { - "_id": 113, + "_id": 85, "type": "LET_STATEMENT", - "loc": 612, + "loc": 488, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "decls": [ { - "_id": 112, + "_id": 84, "type": "ASSIGNMENT", - "loc": 616, + "loc": 492, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "lhs": { - "_id": 108, + "_id": 79, "type": "TERM", - "loc": 616, - "token": { - "type": "identifier", - "value": "last", - "start": 616, - "end": 619 - }, + "loc": 492, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@last" + "kind": "Deferred", + "marker": "resolve_type", + "value": "resp" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "token": { + "type": "identifier", + "value": "resp", + "start": 492, + "end": 495 } }, "rhs": { - "_id": 111, + "_id": 83, "type": "CALL", - "loc": 623, + "loc": 499, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "id": { - "_id": 109, + "_id": 80, "type": "TERM", - "loc": 623, - "token": { - "type": "identifier", - "value": "pop", - "start": 623, - "end": 625 - }, + "loc": 499, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@pop" + "kind": "Deferred", + "marker": "resolve_type", + "value": "process_http_retry" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@pop" + "token": { + "type": "identifier", + "value": "process_http_retry", + "start": 499, + "end": 516 } }, "args": [ { - "_id": 110, + "_id": 81, "type": "TERM", - "loc": 627, - "token": { - "type": "identifier", - "value": "numbers", - "start": 627, - "end": 633 + "loc": 518, + "gomType": { + "kind": "PrimitiveOrAlias", + "typeString": "str" }, + "token": { + "type": "strliteral", + "value": "\"http://www.example.com\"", + "start": 518, + "end": 541 + } + }, + { + "_id": 82, + "type": "TERM", + "loc": 544, "gomType": { "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@numbers" + "typeString": "int" }, - "resultantType": { - "kind": "List", - "name": "Numbers", - "elementType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } + "token": { + "type": "numliteral", + "value": "10", + "start": 544, + "end": 545 } } - ], - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" + ] } } ] }, { - "_id": 120, + "_id": 98, "type": "EXPRESSION_STATEMENT", - "loc": 638, + "loc": 551, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "expr": { - "_id": 119, + "_id": 97, "type": "ACCESS", - "loc": 638, + "loc": 551, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "lhs": { - "_id": 114, + "_id": 86, "type": "TERM", - "loc": 638, + "loc": 551, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "io" + }, "token": { "type": "identifier", "value": "io", - "start": 638, - "end": 639 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" + "start": 551, + "end": 552 } }, "rhs": { - "_id": 118, + "_id": 96, "type": "CALL", - "loc": 641, + "loc": 554, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "id": { - "_id": 115, + "_id": 87, "type": "TERM", - "loc": 641, + "loc": 554, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "log" + }, "token": { "type": "identifier", "value": "log", - "start": 641, - "end": 643 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" + "start": 554, + "end": 556 } }, "args": [ { - "_id": 116, + "_id": 88, "type": "TERM", - "loc": 645, - "token": { - "type": "strliteral", - "value": "\"Popped element: \"", - "start": 645, - "end": 662 - }, + "loc": 558, "gomType": { "kind": "PrimitiveOrAlias", "typeString": "str" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" + "token": { + "type": "strliteral", + "value": "\"Status: \"", + "start": 558, + "end": 567 } }, { - "_id": 117, - "type": "TERM", - "loc": 665, - "token": { - "type": "identifier", - "value": "last", - "start": 665, - "end": 668 - }, + "_id": 91, + "type": "ACCESS", + "loc": 570, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@last" + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" + "lhs": { + "_id": 89, + "type": "TERM", + "loc": 570, + "gomType": { + "kind": "Deferred", + "marker": "resolve_type", + "value": "resp" + }, + "token": { + "type": "identifier", + "value": "resp", + "start": 570, + "end": 573 + } + }, + "rhs": { + "_id": 90, + "type": "TERM", + "loc": 575, + "gomType": { + "kind": "PrimitiveOrAlias", + "typeString": "int" + }, + "token": { + "type": "numliteral", + "value": "0", + "start": 575, + "end": 575 + } } - } - ], - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } - } - }, - { - "_id": 129, - "type": "EXPRESSION_STATEMENT", - "loc": 673, - "expr": { - "_id": 128, - "type": "ACCESS", - "loc": 673, - "lhs": { - "_id": 121, - "type": "TERM", - "loc": 673, - "token": { - "type": "identifier", - "value": "io", - "start": 673, - "end": 674 - }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@io" - } - }, - "rhs": { - "_id": 127, - "type": "CALL", - "loc": 676, - "id": { - "_id": 122, - "type": "TERM", - "loc": 676, - "token": { - "type": "identifier", - "value": "log", - "start": 676, - "end": 678 }, - "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@log" - } - }, - "args": [ { - "_id": 123, + "_id": 92, "type": "TERM", - "loc": 680, - "token": { - "type": "strliteral", - "value": "\"After pop: \"", - "start": 680, - "end": 692 - }, + "loc": 578, "gomType": { "kind": "PrimitiveOrAlias", "typeString": "str" }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "str" + "token": { + "type": "strliteral", + "value": "\" Success: \"", + "start": 578, + "end": 589 } }, { - "_id": 126, + "_id": 95, "type": "ACCESS", - "loc": 695, + "loc": 592, + "gomType": { + "kind": "Deferred", + "marker": "deferred", + "value": "unknown" + }, "lhs": { - "_id": 124, + "_id": 93, "type": "TERM", - "loc": 695, - "token": { - "type": "identifier", - "value": "numbers", - "start": 695, - "end": 701 - }, + "loc": 592, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@numbers" + "kind": "Deferred", + "marker": "resolve_type", + "value": "resp" }, - "resultantType": { - "kind": "List", - "name": "Numbers", - "elementType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" - } + "token": { + "type": "identifier", + "value": "resp", + "start": 592, + "end": 595 } }, "rhs": { - "_id": 125, + "_id": 94, "type": "TERM", - "loc": 703, - "token": { - "type": "identifier", - "value": "length", - "start": 703, - "end": 708 - }, + "loc": 597, "gomType": { - "kind": "PrimitiveOrAlias", - "typeString": "resolve_type@@length" - }, - "resultantType": { "kind": "PrimitiveOrAlias", "typeString": "int" + }, + "token": { + "type": "numliteral", + "value": "1", + "start": 597, + "end": 597 } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "int" } } - ], - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" - } - }, - "resultantType": { - "kind": "PrimitiveOrAlias", - "typeString": "void" + ] } } }