import { parse } from "./parser" import { convertIR } from "./ir" import type { Attr, Decl, Stmt, Type, VarDecl } from "./ast" type SymbolDefn = { attrs: Array, name: string, type: Type } type SymbolMap = { [name: string]: SymbolDefn } // TODO: Support more than one TU export const compile = (source: string): string => { // 1. Parse const ast = parse(source) // 2. Partition declarations and statements const decls = ast.filter((x): x is Decl => x.type == "decl") const stmts = ast.filter((x): x is Stmt => x.type == "stmt") console.log("Declarations", decls) console.log("Statements", stmts) // 3. Create top-level symbol map const symbols = processDecls(decls) console.log("Symbols", symbols) // TODO: Some form of type-checking // 4. Generate IR const ir = convertIR(stmts) console.log("IR", ir) return "" } export const processDecls = (decls: Array): SymbolMap => decls.reduce((symbols, decl) => { const symbol = processVarDecl(symbols, decl) return { ...symbols, [symbol.name]: symbol, } }, {}) export const processVarDecl = (symbols: SymbolMap, decl: VarDecl): SymbolDefn => { if (typeof symbols[decl.name] !== 'undefined') { throw new Error(`a variable named \`${decl.name}' is already defined`) } return { attrs: decl.attrs, name: decl.name, type: decl.args.type, } }