source: src/Common/Eval.cc @ a8ef59e

ADTast-experimentalenumpthread-emulationqualifiedEnum
Last change on this file since a8ef59e was 7ff3e522, checked in by Andrew Beach <ajbeach@…>, 4 years ago

{pass_t Pass::pass; => core_t Pass::core;} To avoid confusion about which pass we are talking about.

  • Property mode set to 100644
File size: 5.3 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// utility.h --
8//
9// Author           : Richard C. Bilson
10// Created On       : Mon May 18 07:44:20 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Wed Jul 24 15:09:06 2019
13// Update Count     : 64
14//
15
16#include <utility> // for pair
17
18#include "Common/PassVisitor.h"
19#include "AST/Pass.hpp"
20#include "InitTweak/InitTweak.h"
21#include "SynTree/Expression.h"
22
23//-------------------------------------------------------------
24// Old AST
25struct EvalOld : public WithShortCircuiting {
26        long long int value = 0;
27        bool valid = true;
28
29        void previsit( const BaseSyntaxNode * ) { visit_children = false; }
30        void postvisit( const BaseSyntaxNode * ) { valid = false; }
31
32        void postvisit( const SizeofExpr * ) {
33        }
34
35        void postvisit( const ConstantExpr * expr ) {
36                value = expr->intValue();
37        }
38
39        void postvisit( const CastExpr * expr ) {
40                auto arg = eval(expr->arg);
41                valid = arg.second;
42                value = arg.first;
43                // TODO: perform type conversion on value if valid
44        }
45
46        void postvisit( const VariableExpr * const expr ) {
47                if ( EnumInstType * inst = dynamic_cast<EnumInstType *>(expr->result) ) {
48                        if ( EnumDecl * decl = inst->baseEnum ) {
49                                if ( decl->valueOf( expr->var, value ) ) { // value filled by valueOf
50                                        return;
51                                }
52                        }
53                }
54                valid = false;
55        }
56
57        void postvisit( const ApplicationExpr * expr ) {
58                DeclarationWithType * function = InitTweak::getFunction(const_cast<ApplicationExpr *>(expr));
59                if ( ! function || function->linkage != LinkageSpec::Intrinsic ) { valid = false; return; }
60                const std::string & fname = function->name;
61                assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() );
62                std::pair<long long int, bool> arg1, arg2;
63                arg1 = eval(expr->args.front());
64                valid = valid && arg1.second;
65                if ( ! valid ) return;
66                if ( expr->args.size() == 2 ) {
67                        arg2 = eval(expr->args.back());
68                        valid = valid && arg2.second;
69                        if ( ! valid ) return;
70                }
71                if (fname == "?+?") {
72                        value = arg1.first + arg2.first;
73                } else if (fname == "?-?") {
74                        value = arg1.first - arg2.first;
75                } else if (fname == "?*?") {
76                        value = arg1.first * arg2.first;
77                } else if (fname == "?/?") {
78                        value = arg1.first / arg2.first;
79                } else if (fname == "?%?") {
80                        value = arg1.first % arg2.first;
81                } else {
82                        valid = false;
83                }
84                // TODO: implement other intrinsic functions
85        }
86};
87
88//-------------------------------------------------------------
89// New AST
90struct EvalNew : public ast::WithShortCircuiting {
91        long long int value = 0;
92        bool valid = true;
93
94        void previsit( const ast::Node * ) { visit_children = false; }
95        void postvisit( const ast::Node * ) { valid = false; }
96
97        void postvisit( const ast::ConstantExpr * expr ) {
98                value = expr->intValue();
99        }
100
101        void postvisit( const ast::SizeofExpr * expr ) {
102                if ( expr->expr ) value = eval(expr->expr).first;
103                else if ( expr->type ) value = eval(expr->expr).first;
104                else SemanticError( expr->location, ::toString( "Internal error: SizeofExpr has no expression or type value" ) );
105        }
106
107        void postvisit( const ast::CastExpr * expr ) {
108                auto arg = eval(expr->arg);
109                valid = arg.second;
110                value = arg.first;
111                // TODO: perform type conversion on value if valid
112        }
113
114        void postvisit( const ast::VariableExpr * expr ) {
115                if ( const ast::EnumInstType * inst = dynamic_cast<const ast::EnumInstType *>(expr->result.get()) ) {
116                        if ( const ast::EnumDecl * decl = inst->base ) {
117                                if ( decl->valueOf( expr->var, value ) ) { // value filled by valueOf
118                                        return;
119                                }
120                        }
121                }
122                valid = false;
123        }
124
125        void postvisit( const ast::ApplicationExpr * expr ) {
126                const ast::DeclWithType * function = InitTweak::getFunction(expr);
127                if ( ! function || function->linkage != ast::Linkage::Intrinsic ) { valid = false; return; }
128                const std::string & fname = function->name;
129                assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() );
130                std::pair<long long int, bool> arg1, arg2;
131                arg1 = eval(expr->args.front());
132                valid = valid && arg1.second;
133                if ( ! valid ) return;
134                if ( expr->args.size() == 2 ) {
135                        arg2 = eval(expr->args.back());
136                        valid = valid && arg2.second;
137                        if ( ! valid ) return;
138                }
139                if (fname == "?+?") {
140                        value = arg1.first + arg2.first;
141                } else if (fname == "?-?") {
142                        value = arg1.first - arg2.first;
143                } else if (fname == "?*?") {
144                        value = arg1.first * arg2.first;
145                } else if (fname == "?/?") {
146                        value = arg1.first / arg2.first;
147                } else if (fname == "?%?") {
148                        value = arg1.first % arg2.first;
149                } else {
150                        valid = false;
151                }
152                // TODO: implement other intrinsic functions
153        }
154};
155
156std::pair<long long int, bool> eval( const Expression * expr) {
157        PassVisitor<EvalOld> ev;
158        if (expr) {
159                expr->accept(ev);
160                return std::make_pair(ev.pass.value, ev.pass.valid);
161        } else {
162                return std::make_pair(0, false);
163        }
164}
165
166std::pair<long long int, bool> eval(const ast::Expr * expr) {
167        ast::Pass<EvalNew> ev;
168        if (expr) {
169                expr->accept(ev);
170                return std::make_pair(ev.core.value, ev.core.valid);
171        } else {
172                return std::make_pair(0, false);
173        }
174}
175
176// Local Variables: //
177// tab-width: 4 //
178// mode: c++ //
179// compile-command: "make install" //
180// End: //
Note: See TracBrowser for help on using the repository browser.