mirror of
				https://git.sfja.dk/Mikkel/slige.git
				synced 2025-10-29 03:48:15 +00:00 
			
		
		
		
	lowerer
This commit is contained in:
		
							parent
							
								
									6ab45ffbed
								
							
						
					
					
						commit
						b9c174d96a
					
				
							
								
								
									
										142
									
								
								compiler/Lowerer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								compiler/Lowerer.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,142 @@ | ||||
| import { Expr, Stmt } from "./ast.ts"; | ||||
| import { Ops } from "./mod.ts"; | ||||
| 
 | ||||
| class Locals { | ||||
|     private localIdCounter = 0; | ||||
|     private symLocalMap: {[key: string]: number} = {} | ||||
| 
 | ||||
|     constructor (private parent?: Locals) {} | ||||
| 
 | ||||
|     defineSym(ident: string) { | ||||
|         this.symLocalMap[ident] = this.localIdCounter | ||||
|         this.localIdCounter++ | ||||
|     } | ||||
| 
 | ||||
|     symLocalId(ident: string): number { | ||||
|         if (ident in this.symLocalMap) { | ||||
|             return this.symLocalMap[ident] | ||||
|         } | ||||
|         if (!this.parent) { | ||||
|             throw new Error(`Could not find syn local id with ident ${ident}`) | ||||
|         } | ||||
|         else { | ||||
|             return this.parent.symLocalId(ident) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export class Lowerer { | ||||
|     private program: number[] = []  | ||||
|     private locals = new Locals() | ||||
| 
 | ||||
| 
 | ||||
|     lower(stmts: Stmt[]) { | ||||
|         for(const stmt of stmts) { | ||||
|             this.lowerStmt(stmt) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     lowerStmt(stmt: Stmt) { | ||||
|         switch (stmt.kind.type) { | ||||
|             case "error": | ||||
|             case "break": | ||||
|             case "return": | ||||
|             case "fn": | ||||
|                 break; | ||||
|             case "let": | ||||
|                 return this.lowerLetStmt(stmt); | ||||
|             case "assign": | ||||
|             case "expr": | ||||
|             } | ||||
|         throw new Error(`Unhandled stmt ${stmt.kind.type}`) | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     lowerLetStmt(stmt: Stmt) { | ||||
|         if (stmt.kind.type !== "let") { | ||||
|             throw new Error(); | ||||
|         } | ||||
|         this.lowerExpr(stmt.kind.value) | ||||
|         this.locals.defineSym(stmt.kind.param.ident), | ||||
|         this.program.push(Ops.StoreLocal) | ||||
|         this.program.push(this.locals.symLocalId(stmt.kind.param.ident)) | ||||
|     } | ||||
| 
 | ||||
|     lowerExpr(expr: Expr) { | ||||
|         switch (expr.kind.type) { | ||||
|             case "string": | ||||
|             case "error": | ||||
|                 break; | ||||
|             case "int": | ||||
|                 return this.lowerInt(expr) | ||||
|             case "ident": | ||||
|             case "group": | ||||
|             case "field": | ||||
|             case "index": | ||||
|             case "call": | ||||
|             case "unary": | ||||
|                 break; | ||||
|             case "binary": | ||||
|                 return this.lowerBinaryExpr(expr) | ||||
|             case "if": | ||||
|             case "bool": | ||||
|             case "null": | ||||
|             case "loop": | ||||
|             case "block": | ||||
|                 break; | ||||
|             case "sym": | ||||
|                 return this.lowerSym(expr) | ||||
|         } | ||||
|         throw new Error(`Unhandled expr ${expr.kind.type}`) | ||||
|     } | ||||
| 
 | ||||
|     lowerInt(expr: Expr) { | ||||
|         if (expr.kind.type !== "int") { | ||||
|             throw new Error(); | ||||
|         } | ||||
|         this.program.push(Ops.PushInt) | ||||
|         this.program.push(expr.kind.value) | ||||
|     } | ||||
| 
 | ||||
|     lowerSym(expr: Expr) { | ||||
|         if (expr.kind.type !== "sym") { | ||||
|             throw new Error(); | ||||
|         } | ||||
|         if (expr.kind.defType == "let") { | ||||
|             this.program.push(Ops.LoadLocal) | ||||
|             this.program.push(this.locals.symLocalId(expr.kind.ident)); | ||||
|             return; | ||||
|         } | ||||
|         throw new Error(`Unhandled sym deftype ${expr.kind.defType}`); | ||||
|     } | ||||
| 
 | ||||
|     lowerBinaryExpr(expr: Expr) { | ||||
|         if (expr.kind.type !== "binary") { | ||||
|             throw new Error(); | ||||
|         } | ||||
|         this.lowerExpr(expr.kind.left); | ||||
|         this.lowerExpr(expr.kind.right); | ||||
|         if (expr.vtype?.type == "int") { | ||||
|             switch (expr.kind.binaryType) { | ||||
|                 case "+": | ||||
|                     this.program.push(Ops.Add); | ||||
|                     return | ||||
|                 case "*": | ||||
|                     this.program.push(Ops.Multiply); | ||||
|                     return | ||||
|                 case "==": | ||||
|                 case "-": | ||||
|                 case "/": | ||||
|                 case "!=": | ||||
|                 case "<": | ||||
|                 case ">": | ||||
|                 case "<=": | ||||
|                 case ">=": | ||||
|                 case "or": | ||||
|                 case "and": | ||||
|             } | ||||
|             throw new Error("Unhandled binary type") | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user