Untitled

 avatar
unknown
plain_text
6 days ago
3.1 kB
7
Indexable
@Override
    public Ir.Expr.ObjectExpr visit(Ast.Expr.ObjectExpr ast) throws AnalyzeException {
        if (ast.name().isPresent()){
            if (Environment.TYPES.containsKey(ast.name().get())){
                throw new AnalyzeException("Object " + ast.name().get() + " is already defined");
            }
        }

        Scope objScope = new Scope(null);

        List<Ir.Stmt.Let> fields = new ArrayList<>();
        for (var field : ast.fields()){
            Optional<Type> type = Optional.empty();
            if (field.type().isPresent()) {
                type  = Optional.of(Environment.TYPES.get(field.type()));
            }
            Optional<Ir.Expr> value = field.value().isPresent()
                    ? Optional.of(visit(field.value().get()))
                    : Optional.empty();

            var variableType = type.or(() -> value.map(expr -> expr.type())).orElse(Type.ANY);
            if (value.isPresent()) {
                requireSubtype(value.get().type(), variableType);
            }
            objScope.define(field.name(), variableType);
            fields.add(new Ir.Stmt.Let(field.name(), variableType, value));
        }

        List<Ir.Stmt.Def> methods = new ArrayList<>();
        for (var method : ast.methods()){
            if (scope.get(method.name(), true).isPresent()){
                throw new AnalyzeException("Method " + ast.name() + " has already been defined in the current scope");
            }
            List<Type> types = new ArrayList<>();
            for (var param : method.parameterTypes()) {
                if (scope.get(param.get(), true).isPresent()){
                    throw new AnalyzeException("Function " + ast.name() + " has already been defined in the current scope");
                }
                Type type = Environment.TYPES.get(param.get());
                types.add(type);
            }
            Type returnType = Type.ANY;
            if (method.returnType().isPresent()){
                returnType = Environment.TYPES.get(method.returnType().get());
            }
            objScope.define(method.name(), new Type.Function(types, returnType));

            int index = 0;
            var testScope = new Scope(objScope);

            List<Ir.Stmt.Def.Parameter> params = new ArrayList<>();
            for (var param : method.parameters()) {
                testScope.define(param, types.get(index));
                params.add(new Ir.Stmt.Def.Parameter(param, types.get(index)));
                index++;
            }
            testScope.define("$RETURNS", returnType);

            List<Ir.Stmt> body = new ArrayList<>();
            for (var stmts : method.body()){
                var currentStmt = visit(stmts);
                body.add(currentStmt);
            }
            methods.add(new Ir.Stmt.Def(method.name(), params, returnType, body));
        }


        Type obj = new Type.Object(objScope);
        return new Ir.Expr.ObjectExpr(ast.name(), fields, methods, obj);
    }
Editor is loading...
Leave a Comment