diff --git a/packages/boringlang/src/commands/run.ts b/packages/boringlang/src/commands/run.ts index 8907841..c0fce2e 100644 --- a/packages/boringlang/src/commands/run.ts +++ b/packages/boringlang/src/commands/run.ts @@ -5,6 +5,7 @@ import TraitChecker from "../types/trait_checker"; import { TypeAliasResolver } from "../types/type_alias_resolution"; import { TypeSystem } from "../types/type_system"; import { TypeChecker } from "../types/type_checker"; +import { TypeResolver } from "../types/type_resolver"; export const run = defineCommand({ name: "run", @@ -28,9 +29,11 @@ export const run = defineCommand({ const aliasResolvedAst = new TypeAliasResolver().withModule(ast); const typeSystem = new TypeSystem(); const typeChecker = new TypeChecker(); + const typeResolver = new TypeResolver(); typeChecker.withModule(aliasResolvedAst, typeSystem); typeSystem.solve(); - console.log(JSON.stringify(typeSystem, null, 2)); + const typeResolvedAst = typeResolver.withModule(aliasResolvedAst, typeSystem); + console.log(JSON.stringify(typeResolvedAst, null, 2)); // console.log(JSON.stringify(aliasResolvedAst, null, 2)); } else { diff --git a/packages/boringlang/src/types/type_resolver.ts b/packages/boringlang/src/types/type_resolver.ts new file mode 100644 index 0000000..b160844 --- /dev/null +++ b/packages/boringlang/src/types/type_resolver.ts @@ -0,0 +1,211 @@ +import { + AssignmentStatement, + Block, + containsReturn, + Expression, + Function, + FunctionCall, + FunctionDeclaration, + functionToType, + IfExpression, + Impl, + LetStatement, + LiteralStruct, + Module, + newVoid, + Operation, + ReturnStatement, + StructGetter, + StructTypeDeclaration, + TraitTypeDeclaration, + TypeUsage, + VariableUsage, +} from "../parse/ast"; +import { newContext } from "./builtins"; +import { Context, deepCopy, typeExists } from "./context"; +import { TypeSystem } from "./type_system"; + +export class TypeResolver { + withModule = (module: Module, typeSystem: TypeSystem) => { + const result = deepCopy(module); + // environment set up, actually recurse. + for (const [i, item] of module.items.entries()) { + if (item.moduleItem === "Function") { + result.items[i] = this.withFunction(item, typeSystem); + } + if (item.moduleItem === "Impl") { + result.items[i] = this.withImpl(item, typeSystem); + } + if (item.moduleItem === "StructTypeDeclaration") { + result.items[i] = this.withStructDeclaration(item, typeSystem); + } + if (item.moduleItem === "TraitTypeDeclaration") { + result.items[i] = this.withTrait(item, typeSystem); + } + } + return result; + }; + + withFunction = (fn: Function, typeSystem: TypeSystem) => { + const result = deepCopy(fn); + result.declaration = this.withFunctionDeclaration(fn.declaration, typeSystem); + result.block = this.withBlock(fn.block, typeSystem); + return result; + }; + + withFunctionDeclaration = (def: FunctionDeclaration, typeSystem: TypeSystem) => { + const result = deepCopy(def); + result.arguments = def.arguments.map((arg) => { + const resultArg = deepCopy(arg); + resultArg.type = typeSystem.resolveType(arg.type); + return resultArg; + }); + return result; + }; + + withImpl = (impl: Impl, typeSystem: TypeSystem) => { + const result = deepCopy(impl); + for (const [i, fn] of impl.functions.entries()) { + result.functions[i] = this.withFunction(fn, typeSystem); + } + return result; + }; + + withStructDeclaration = (struct: StructTypeDeclaration, typeSystem: TypeSystem) => { + const result = deepCopy(struct); + for (const [i, field] of struct.fields.entries()) { + result.fields[i] = { name: field.name, type: typeSystem.resolveType(field.type) }; + } + return result; + }; + + withTrait = (trait: TraitTypeDeclaration, typeSystem: TypeSystem) => { + const result = deepCopy(trait); + for (const [i, method] of trait.functions.entries()) { + result.functions[i] = this.withFunctionDeclaration(method, typeSystem); + } + return result; + }; + + withBlock = (block: Block, typeSystem: TypeSystem) => { + const result = deepCopy(block); + for (const [i, statement] of block.statements.entries()) { + if (statement.statementType === "AssignmentStatement") { + result.statements[i] = this.withAssignmentStatement(statement, typeSystem); + } + if (statement.statementType === "LetStatement") { + result.statements[i] = this.withLetStatement(statement, typeSystem); + } + if (statement.statementType === "Expression") { + result.statements[i] = this.withExpression(statement, typeSystem); + } + if (statement.statementType === "ReturnStatement") { + result.statements[i] = this.withReturnStatement(statement, typeSystem); + } + result.type = typeSystem.resolveType(block.type); + } + return result; + }; + + withAssignmentStatement = (statement: AssignmentStatement, typeSystem: TypeSystem) => { + const result = deepCopy(statement); + if (statement.source.expressionType == "StructGetter") { + result.source = this.withStructGetter(statement.source, typeSystem); + } + if (statement.source.expressionType == "VariableUsage") { + result.source = this.withVariableUsage(statement.source, typeSystem); + } + result.expression = this.withExpression(statement.expression, typeSystem); + return result; + }; + + withLetStatement = (statement: LetStatement, typeSystem: TypeSystem) => { + const result = deepCopy(statement); + result.expression = this.withExpression(statement.expression, typeSystem); + result.type = typeSystem.resolveType(statement.type); + return result; + }; + + withReturnStatement = (statement: ReturnStatement, typeSystem: TypeSystem) => { + const result = deepCopy(statement); + result.source = this.withExpression(statement.source, typeSystem); + return result; + }; + + withExpression = (expression: Expression, typeSystem: TypeSystem) => { + const result = deepCopy(expression); + result.type = typeSystem.resolveType(expression.type); + + if (expression.subExpression.expressionType === "LiteralStruct") { + result.subExpression = this.withLiteralStruct(expression.subExpression, typeSystem); + } + if (expression.subExpression.expressionType === "FunctionCall") { + result.subExpression = this.withFunctionCall(expression.subExpression, typeSystem); + } + if (expression.subExpression.expressionType === "VariableUsage") { + result.subExpression = this.withVariableUsage(expression.subExpression, typeSystem); + } + if (expression.subExpression.expressionType === "IfExpression") { + result.subExpression = this.withIfExpression(expression.subExpression, typeSystem); + } + if (expression.subExpression.expressionType === "StructGetter") { + result.subExpression = this.withStructGetter(expression.subExpression, typeSystem); + } + if (expression.subExpression.expressionType === "Block") { + result.subExpression = this.withBlock(expression.subExpression, typeSystem); + } + if (expression.subExpression.expressionType === "Operation") { + result.subExpression = this.withOperation(expression.subExpression, typeSystem); + } + return result; + }; + + withLiteralStruct = (literal: LiteralStruct, typeSystem: TypeSystem) => { + const result = deepCopy(literal); + for (const [i, field] of literal.fields.entries()) { + result.fields[i].expression = this.withExpression(field.expression, typeSystem); + } + result.type = typeSystem.resolveType(literal.type); + return result; + }; + + withFunctionCall = (fnCall: FunctionCall, typeSystem: TypeSystem) => { + const result = deepCopy(fnCall); + result.type = typeSystem.resolveType(fnCall.type); + result.source = this.withExpression(fnCall.source, typeSystem); + for (const [i, arg] of fnCall.arguments.entries()) { + result.arguments[i] = this.withExpression(arg, typeSystem); + } + return result; + }; + + withVariableUsage = (usage: VariableUsage, typeSystem: TypeSystem) => { + const result = deepCopy(usage); + result.type = typeSystem.resolveType(usage.type); + return result; + }; + + withIfExpression = (ifExpression: IfExpression, typeSystem: TypeSystem) => { + const result = deepCopy(ifExpression); + result.type = typeSystem.resolveType(ifExpression.type); + result.condition = this.withExpression(ifExpression.condition, typeSystem); + result.block = this.withBlock(ifExpression.block, typeSystem); + result.else = ifExpression.else ? this.withBlock(ifExpression.else, typeSystem) : null; + return result; + }; + + withStructGetter = (structGetter: StructGetter, typeSystem: TypeSystem) => { + const result = deepCopy(structGetter); + result.type = typeSystem.resolveType(structGetter.type); + result.source = this.withExpression(structGetter.source, typeSystem); + return result; + }; + + withOperation = (op: Operation, typeSystem: TypeSystem) => { + const result = deepCopy(op); + result.type = typeSystem.resolveType(op.type); + result.left = this.withExpression(op.left, typeSystem); + result.right = this.withExpression(op.right, typeSystem); + return result; + }; +} diff --git a/packages/boringlang/src/types/type_system.ts b/packages/boringlang/src/types/type_system.ts index d366fe4..45c53d4 100644 --- a/packages/boringlang/src/types/type_system.ts +++ b/packages/boringlang/src/types/type_system.ts @@ -100,8 +100,11 @@ export class TypeSystem { comparison.left.name.text, comparison.operation.name, ); - this.result[comparison.right.name] = attrType; - comparison.right = attrType; + const [result, found] = this.equateTypes(attrType, comparison.right); + if (found) { + comparison.right = result; + foundUpdate = true; + } } // check if (comparison.right.typeUsage !== "UnknownTypeUsage") {