js实现一个简单的ast执行器

class Environment {
    constructor(outer = null) {
        this.variables = {};
        this.outer = outer;
    }

    get(name) {
        if (name in this.variables) {
            return this.variables[name];
        } else if (this.outer !== null) {
            return this.outer.get(name);
        } else {
            throw new ReferenceError(`Variable "${name}" is not defined.`);
        }
    }

    set(name, value) {
        this.variables[name] = value;
    }

    define(name, value) {
        this.variables[name] = value;
    }
}

class Interpreter {
    constructor() {
        this.globalEnv = new Environment();
        this.currentEnv = this.globalEnv;
    }

    interpret(node) {
        switch (node.type) {
            case 'Program':
                return this.interpretProgram(node);
            case 'VariableDeclaration':
                return this.interpretVariableDeclaration(node);
            case 'FunctionDeclaration':
                return this.interpretFunctionDeclaration(node);
            case 'ExpressionStatement':
                return this.interpret(node.expression);
            case 'BlockStatement':
                return this.interpretBlockStatement(node);
            case 'AssignmentExpression':
                return this.interpretAssignmentExpression(node);
            case 'BinaryExpression':
                return this.interpretBinaryExpression(node);
            case 'Literal':
                return node.value;
            case 'Identifier':
                return this.currentEnv.get(node.name);
            case 'CallExpression':
                return this.interpretCallExpression(node);
            case 'ReturnStatement':
                return this.interpretReturnStatement(node);
            default:
                throw new Error(`Unknown node type: ${node.type}`);
        }
    }

    interpretProgram(node) {
        for (const statement of node.body) {
            this.interpret(statement);
        }
    }

    interpretVariableDeclaration(node) {
        for (const declaration of node.declarations) {
            const name = declaration.id.name;
            const value = declaration.init ? this.interpret(declaration.init) : undefined;
            this.currentEnv.define(name, value);
        }
    }

    interpretFunctionDeclaration(node) {
        const name = node.id.name;
        this.currentEnv.define(name, node);
    }

    interpretBlockStatement(node) {
        for (const statement of node.body) {
            const result = this.interpret(statement);
            if (statement.type === 'ReturnStatement') {
                return result;
            }
        }
    }

    interpretAssignmentExpression(node) {
        const name = node.left.name;
        const value = this.interpret(node.right);
        this.currentEnv.set(name, value);
    }

    interpretBinaryExpression(node) {
        const left = this.interpret(node.left);
        const right = this.interpret(node.right);
        switch (node.operator) {
            case '+':
                return left + right;
            case '-':
                return left - right;
            case '*':
                return left * right;
            case '/':
                return left / right;
            default:
                throw new Error(`Unknown binary operator: ${node.operator}`);
        }
    }

    interpretCallExpression(node) {
        const func = this.currentEnv.get(node.callee.name);
        const args = node.arguments.map(arg => this.interpret(arg));

        const funcEnv = new Environment(this.currentEnv);
        for (let i = 0; i < func.params.length; i++) {
            funcEnv.define(func.params[i].name, args[i]);
        }

        const interpreter = new Interpreter();
        interpreter.currentEnv = funcEnv;

        return interpreter.interpret(func.body);
    }

    interpretReturnStatement(node) {
        return this.interpret(node.argument);
    }
}


const ast = {
    "type": "Program",
    "body": [
        {
            "type": "VariableDeclaration",
            "declarations": [
                {
                    "type": "VariableDeclarator",
                    "id": {
                        "type": "Identifier",
                        "name": "x"
                    },
                    "init": {
                        "type": "BinaryExpression",
                        "operator": "+",
                        "left": {
                            "type": "Literal",
                            "value": 10,
                            "raw": "10"
                        },
                        "right": {
                            "type": "Literal",
                            "value": 20,
                            "raw": "20"
                        }
                    }
                }
            ],
            "kind": "var"
        },
        {
            "type": "FunctionDeclaration",
            "id": {
                "type": "Identifier",
                "name": "add"
            },
            "params": [
                {
                    "type": "Identifier",
                    "name": "a"
                },
                {
                    "type": "Identifier",
                    "name": "b"
                }
            ],
            "body": {
                "type": "BlockStatement",
                "body": [
                    {
                        "type": "ReturnStatement",
                        "argument": {
                            "type": "BinaryExpression",
                            "operator": "+",
                            "left": {
                                "type": "Identifier",
                                "name": "a"
                            },
                            "right": {
                                "type": "Identifier",
                                "name": "b"
                            }
                        }
                    }
                ]
            }
        },
        {
            "type": "ExpressionStatement",
            "expression": {
                "type": "AssignmentExpression",
                "operator": "=",
                "left": {
                    "type": "Identifier",
                    "name": "x"
                },
                "right": {
                    "type": "CallExpression",
                    "callee": {
                        "type": "Identifier",
                        "name": "add"
                    },
                    "arguments": [
                        {
                            "type": "Identifier",
                            "name": "x"
                        },
                        {
                            "type": "Literal",
                            "value": 5,
                            "raw": "5"
                        }
                    ]
                }
            }
        }
    ]
};

const interpreter = new Interpreter();
interpreter.interpret(ast);

console.log(interpreter.currentEnv);  // 应该输出35

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值