Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Validate/ReplacePseudoFunc.cpp

    r544deb9 rac939461  
     1#include "AST/Decl.hpp"
     2#include "AST/Pass.hpp"
     3#include "AST/Stmt.hpp"
     4#include "AST/Inspect.hpp"
     5#include "Common/utility.h"
    16#include "ReplacePseudoFunc.hpp"
    27
    3 #include <set>
    4 
    5 #include "AST/Decl.hpp"
    6 #include "AST/Inspect.hpp"
    7 #include "AST/Pass.hpp"
    8 #include "AST/Stmt.hpp"
    9 #include "Common/utility.h"
    10 #include "ResolvExpr/Resolver.h"
    11 #include "SymTab/Mangler.h"  // for Mangler
    128namespace Validate {
    139
    1410namespace {
    1511
    16 std::set<std::string> queryLabels;
    17 std::set<std::string> queryValues;
    18 
    19 struct FindGenEnumArray final : public ast::WithShortCircuiting {
    20     void previsit(const ast::ApplicationExpr* enumDecl);
     12struct ReplacePseudoFuncCore {
     13    ast::Expr const * postvisit( ast::ApplicationExpr const * decl );
    2114};
    22 
    23 void FindGenEnumArray::previsit(const ast::ApplicationExpr* expr) {
    24     auto fname = ast::getFunctionName(expr);
    25     if (fname == "labelE" || fname == "valueE") {
    26         if (expr->args.size() != 1) {
    27             SemanticError(expr, "Position Expression only take one parameter");
    28         }
    29         const ast::VariableExpr* arg =
    30             expr->args.front().as<const ast::VariableExpr>();
    31         if (!arg) {
    32             SemanticError(expr, "Unimplement Pseudo Function Cases");
    33         }
    34         const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
    35         const std::string referredName = argAsVar->name;
    36         const ast::EnumInstType* argType =
    37             argAsVar->type.as<const ast::EnumInstType>();
    38         if (!argType) {
    39             SemanticError(
    40                 argAsVar,
    41                 "Position can only be used on an enumeration instance");
    42         }
    43         ast::ptr<ast::EnumDecl> base = argType->base;
    44         assert(base);
    45         if (fname == "labelE") queryLabels.insert(base->name);
    46         if (fname == "valueE") queryValues.insert(base->name);
    47     }
    4815}
    4916
    50 struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,
    51                                          public ast::WithSymbolTable,
    52                                          public ast::WithShortCircuiting {
    53     void previsit(const ast::EnumDecl* enumDecl);
    54 };
    55 
    56 void PseudoFuncGenerateRoutine::previsit(const ast::EnumDecl* enumDecl) {
    57     visit_children = false;
    58     const CodeLocation& location = enumDecl->location;
    59     if (enumDecl->members.size() == 0 || !enumDecl->base) return;
    60 
    61     std::vector<ast::ptr<ast::Init>> inits;
    62     std::vector<ast::ptr<ast::Init>> labels;
    63     for (const ast::Decl* mem : enumDecl->members) {
    64         auto memAsObjectDecl = dynamic_cast<const ast::ObjectDecl*>(mem);
    65         inits.emplace_back(memAsObjectDecl->init);
    66         labels.emplace_back(new ast::SingleInit(
    67             location, ast::ConstantExpr::from_string(location, mem->name)));
    68     }
    69     if (queryValues.count(enumDecl->name)) {
    70         auto init = new ast::ListInit(location, std::move(inits));
    71         auto values = new ast::ObjectDecl(
    72             location, "values_" + enumDecl->name,
    73             new ast::ArrayType(
    74                 enumDecl->base,
    75                 ast::ConstantExpr::from_int(location, enumDecl->members.size()),
    76                 ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),
    77             init, ast::Storage::Static, ast::Linkage::AutoGen);
    78         symtab.addId(values);
    79         values->mangleName = Mangle::mangle(values);
    80         declsToAddAfter.push_back(values);
    81     }
    82     if (queryLabels.count(enumDecl->name)) {
    83         auto label_strings = new ast::ListInit(location, std::move(labels));
    84         auto label_arr = new ast::ObjectDecl(
    85             location, "labels_" + enumDecl->name,
    86             new ast::ArrayType(
    87                 new ast::PointerType(new ast::BasicType{ast::BasicType::Char}),
    88                 ast::ConstantExpr::from_int(location, enumDecl->members.size()),
    89                 ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),
    90             label_strings, ast::Storage::Static, ast::Linkage::AutoGen);
    91         symtab.addId(label_arr);
    92         label_arr->mangleName = Mangle::mangle(label_arr);
    93         declsToAddAfter.push_back(label_arr);
    94     }
    95 }
    96 
    97 struct ReplacePseudoFuncCore : public ast::WithShortCircuiting,
    98                                public ast::WithSymbolTable,
    99                                public ast::WithConstTranslationUnit {
    100     ast::Expr const* postvisit(ast::ApplicationExpr const* decl);
    101 };
    102 
    103 ast::Expr const* ReplacePseudoFuncCore::postvisit(
    104     ast::ApplicationExpr const* expr) {
    105     auto fname = ast::getFunctionName(expr);
    106     auto location = expr->location;
    107     if (fname == "posE" || fname == "valueE" || fname == "labelE") {
    108         if (expr->args.size() != 1) {
    109             SemanticError(expr,
    110                           "Pseudo Enum Expression only take one parameter");
     17ast::Expr const * ReplacePseudoFuncCore::postvisit( ast::ApplicationExpr const * expr) {
     18    auto fname = ast::getFunctionName( expr );
     19    if ( fname == "posE" ) {
     20        // std::cerr << "Found App in ReplacePseudoFunc" << std::endl;
     21        if ( expr->args.size() != 1 ) {
     22            SemanticError( expr, "Position Expression only take one parameter" );
    11123        }
    112         ast::ptr<ast::VariableExpr> arg =
    113             expr->args.front().as<const ast::VariableExpr>();
    114         if (!arg) {
    115             SemanticError(expr, "Unimplement Pseudo Function Cases");
     24        const ast::VariableExpr * arg = expr->args.front().as<const ast::VariableExpr>();
     25        if ( !arg ) {
     26            SemanticError( expr, "Unimplement Pseudo Function Cases" );
    11627        }
    117         const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
     28        const ast::ObjectDecl * argAsVar = arg->var.as<const ast::ObjectDecl>();
    11829        const std::string referredName = argAsVar->name;
    119         const ast::EnumInstType* argType =
    120             argAsVar->type.as<const ast::EnumInstType>();
    121         if (!argType) {
    122             SemanticError(argAsVar,
    123                           "Pseudo Enum Expression can only be used on an "
    124                           "enumeration instance");
     30        const ast::EnumInstType * argType = argAsVar->type.as<const ast::EnumInstType>();
     31        if ( !argType ) {
     32            SemanticError( argAsVar, "Position can only be used on an enumeration instance" );
    12533        }
    126         const ast::EnumDecl* base = argType->base;
    127         for (size_t i = 0; i < base->members.size(); i++) {
    128             if (base->members[i]->name == referredName) {
    129                 if (fname == "posE")
    130                     return ast::ConstantExpr::from_int(expr->location, i);
    131                 else if (fname == "labelE")
    132                     return ast::ConstantExpr::from_string(expr->location,
    133                                                           referredName);
    134                 else
    135                     return new ast::TypeExpr(expr->location, argType);
    136             }
    137         }
    138 
    139         ResolvExpr::ResolveContext context{symtab, transUnit().global};
    140 
    141         if (fname == "labelE") {
    142             ast::Expr* toResolve =
    143                 new ast::NameExpr(expr->location, "labels_" + base->name);
    144             auto result = ResolvExpr::findVoidExpression(toResolve, context);
    145             if (result.get()) {
    146                 auto arrAsVar = result.strict_as<ast::VariableExpr>();
    147                 auto untyped = new ast::UntypedExpr(
    148                     location, new ast::NameExpr(location, "?[?]"),
    149                     {new ast::VariableExpr(*arrAsVar),
    150                      ast::ConstantExpr::from_int(
    151                          location,
    152                          0)});  /// TODO: dummy value.
    153                                 /// To make it works need to change the unifier
    154 
    155                 auto typedResult =
    156                     ResolvExpr::findVoidExpression(untyped, context);
    157                 if (result.get()) {
    158                     ast::ptr<ast::ApplicationExpr> ret =
    159                         typedResult.strict_as<ast::ApplicationExpr>();
    160                     return new ast::ApplicationExpr(*ret);
    161                 }
    162             }
    163         }
    164        
    165         if (fname == "valueE") {
    166             ast::Expr* toResolve =
    167                 new ast::NameExpr(expr->location, "values_" + base->name);
    168             auto result = ResolvExpr::findVoidExpression(toResolve, context);
    169             if (result.get()) {
    170                 auto arrAsVar = result.strict_as<ast::VariableExpr>();
    171                 auto untyped = new ast::UntypedExpr(
    172                     location, new ast::NameExpr(location, "?[?]"),
    173                     {new ast::VariableExpr(*arrAsVar),
    174                      ast::ConstantExpr::from_int(
    175                          location,
    176                          0)});  /// TODO: dummy value.
    177                                 /// To make it works need to change the unifier
    178 
    179                 auto typedResult =
    180                     ResolvExpr::findVoidExpression(untyped, context);
    181                 if (result.get()) {
    182                     ast::ptr<ast::ApplicationExpr> ret =
    183                         typedResult.strict_as<ast::ApplicationExpr>();
    184                     return new ast::ApplicationExpr(*ret);
    185                 }
     34        const ast::EnumDecl * base = argType->base;
     35        for ( size_t i = 0; i < base->members.size(); i++ ) {
     36            if ( base->members[i]->name == referredName ) {
     37                return ast::ConstantExpr::from_int( expr->location, i );
    18638            }
    18739        }
     
    19042}
    19143
    192 }  // namespace
    19344
    194 void replacePseudoFunc(ast::TranslationUnit& translationUnit) {
    195     ast::Pass<FindGenEnumArray>::run(translationUnit);
    196     ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
    197     ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
     45
     46void replacePseudoFunc( ast::TranslationUnit & translationUnit ) {
     47    ast::Pass<ReplacePseudoFuncCore>::run( translationUnit );
    19848}
    199 }  // namespace Validate
     49
     50}
Note: See TracChangeset for help on using the changeset viewer.