From 762c1a0f4554774b7d2da8dfc0fa24aa53bedd92 Mon Sep 17 00:00:00 2001 From: SFJ Date: Tue, 5 Nov 2024 14:49:26 +0100 Subject: [PATCH] Add to chapter 8 --- compiler/chapter_7.md | 2 +- compiler/chapter_8.md | 131 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 129 insertions(+), 4 deletions(-) diff --git a/compiler/chapter_7.md b/compiler/chapter_7.md index 16cc333..09cf53c 100644 --- a/compiler/chapter_7.md +++ b/compiler/chapter_7.md @@ -126,7 +126,7 @@ class Resolver { return; } if (expr.kind.type === "ident") { - this.resolveIdentexpr(expr, syms); + this.resolveIdentExpr(expr, syms); return; } // ... diff --git a/compiler/chapter_8.md b/compiler/chapter_8.md index 0ee8329..7d6391d 100644 --- a/compiler/chapter_8.md +++ b/compiler/chapter_8.md @@ -211,13 +211,19 @@ When checking the types, we need to store the resulting value types. We'll choos ```ts type Expr = { // ... - valueType: ValueType, + vtype?: ValueType, } ``` ```ts type Stmt = { // ... - valueType: ValueType, + vtype?: ValueType, +} +``` +```ts +type Param = { + // ... + vtype?: ValueType, } ``` @@ -312,6 +318,9 @@ class Checker { // ... public checkExpr(expr: Expr): VType { const pos = expr.pos; + if (expr.kind.type === "error") { + throw new Error("error in AST"); + } // ... throw new Error(`unknown expression ${expr.type}`); } @@ -319,6 +328,122 @@ class Checker { } ``` -**To be finished.** +The `checkExpr` method takes an AST expression and returns a value type. + +### 8.5.1 Checking symbol expressions + +```ts +class Checker { + // ... + public checkExpr(expr: Expr): VType { + // ... + if (expr.kind.type === "sym") { + return this.checkSymExpr(expr); + } + // ... + } + // ... +} +``` + +Because checking symbols is a bit involved, we'll defer it to the `checkSymExpr` method. + +### 8.5.2 Checking literal expressions + +Literal expressions are all expressions with a direct value, including null, ints, bools and strings. + +```ts +class Checker { + // ... + public checkExpr(expr: Expr): VType { + // ... + if (expr.kind.type === "null") { + return { type: "null" }; + } + if (expr.kind.type === "int") { + return { type: "int" }; + } + if (expr.kind.type === "bool") { + return { type: "bool" }; + } + if (expr.kind.type === "string") { + return { type: "string" }; + } + // ... + } + // ... +} +``` + +All literal types have a definite corresponding type. + +### 8.5.3 Checking binary expressions + +```ts +const binaryOperations: {}[] = [ + +]; +// ... +class Checker { + // ... + public checkExpr(expr: Expr): VType { + // ... + if (expr.kind.type === "binary") { + const left = this.checkExpr(expr.kind.left); + const right = this.checkExpr(expr.kind.right); + if (left.type === "int" && right.type === "int") { + return { type: "int" }; + } + if (left.type === "string" && right.type === "string") { + return {} + } + } + // ... + } + // ... +} +``` + + + +```ts +class Checker { + // ... + public checkSymExpr(expr: Expr): VType { + // ... + if (expr.kind.type === "sym") { + if (expr.kind.defType === "let") { + const vtype = expr.kind.param.valueType; + if (vtype.type === "error") { + return { type: "error" }; + } + if (vtype.type === "unknown") { + this.report("unknown type", pos); + return { type: "error" }; + } + return vtype; + } + if (expr.kind.defType === "fn") { + const params = expr.kind.stmt.params + .map(param => this.checkType(param.etype!)); + const returnType = this.checkType(expr.kind.stmt.returnType); + return { type: "fn", params, returnType }; + } + if (expr.kind.defType === "fn_param") { + return this.checkType(expr.kind.param.etype!); + } + if (expr.kind.defType === "builtin") { + // ... + } + throw new Error(`unhandled defType ${expr.kind.defType}`); + } + // ... + } + // ... +} +``` + + +