source: src/Common/Eval.cc @ 39156ed

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 39156ed was d7aa12c, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Implemented eval for new AST

  • Property mode set to 100644
File size: 4.9 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 : Sun May  6 22:24:16 2018
13// Update Count     : 40
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( BaseSyntaxNode * ) { visit_children = false; }
30        void postvisit( BaseSyntaxNode * ) { valid = false; }
31
32        void postvisit( ConstantExpr * expr ) {
33                value = expr->intValue();
34        }
35
36        void postvisit( CastExpr * expr ) {
37                auto arg = eval(expr->arg);
38                valid = arg.second;
39                value = arg.first;
40                // TODO: perform type conversion on value if valid
41        }
42
43        void postvisit( VariableExpr * expr ) {
44                if ( EnumInstType * inst = dynamic_cast<EnumInstType *>(expr->result) ) {
45                        if ( EnumDecl * decl = inst->baseEnum ) {
46                                if ( decl->valueOf( expr->var, value ) ) { // value filled by valueOf
47                                        return;
48                                }
49                        }
50                }
51                valid = false;
52        }
53
54        void postvisit( ApplicationExpr * expr ) {
55                DeclarationWithType * function = InitTweak::getFunction(expr);
56                if ( ! function || function->linkage != LinkageSpec::Intrinsic ) { valid = false; return; }
57                const std::string & fname = function->name;
58                assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() );
59                std::pair<long long int, bool> arg1, arg2;
60                arg1 = eval(expr->args.front());
61                valid = valid && arg1.second;
62                if ( ! valid ) return;
63                if ( expr->args.size() == 2 ) {
64                        arg2 = eval(expr->args.back());
65                        valid = valid && arg2.second;
66                        if ( ! valid ) return;
67                }
68                if (fname == "?+?") {
69                        value = arg1.first + arg2.first;
70                } else if (fname == "?-?") {
71                        value = arg1.first - arg2.first;
72                } else if (fname == "?*?") {
73                        value = arg1.first * arg2.first;
74                } else if (fname == "?/?") {
75                        value = arg1.first / arg2.first;
76                } else if (fname == "?%?") {
77                        value = arg1.first % arg2.first;
78                } else {
79                        valid = false;
80                }
81                // TODO: implement other intrinsic functions
82        }
83};
84
85//-------------------------------------------------------------
86// New AST
87struct EvalNew : public ast::WithShortCircuiting {
88        long long int value = 0;
89        bool valid = true;
90
91        void previsit( const ast::Node * ) { visit_children = false; }
92        void postvisit( const ast::Node * ) { valid = false; }
93
94        void postvisit( const ast::ConstantExpr * expr ) {
95                value = expr->intValue();
96        }
97
98        void postvisit( const ast::CastExpr * expr ) {
99                auto arg = eval(expr->arg);
100                valid = arg.second;
101                value = arg.first;
102                // TODO: perform type conversion on value if valid
103        }
104
105        void postvisit( const ast::VariableExpr * expr ) {
106                if ( const ast::EnumInstType * inst = dynamic_cast<const ast::EnumInstType *>(expr->result.get()) ) {
107                        if ( const ast::EnumDecl * decl = inst->base ) {
108                                if ( decl->valueOf( expr->var, value ) ) { // value filled by valueOf
109                                        return;
110                                }
111                        }
112                }
113                valid = false;
114        }
115
116        void postvisit( const ast::ApplicationExpr * expr ) {
117                const ast::DeclWithType * function = InitTweak::getFunction(expr);
118                if ( ! function || function->linkage != ast::Linkage::Intrinsic ) { valid = false; return; }
119                const std::string & fname = function->name;
120                assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() );
121                std::pair<long long int, bool> arg1, arg2;
122                arg1 = eval(expr->args.front());
123                valid = valid && arg1.second;
124                if ( ! valid ) return;
125                if ( expr->args.size() == 2 ) {
126                        arg2 = eval(expr->args.back());
127                        valid = valid && arg2.second;
128                        if ( ! valid ) return;
129                }
130                if (fname == "?+?") {
131                        value = arg1.first + arg2.first;
132                } else if (fname == "?-?") {
133                        value = arg1.first - arg2.first;
134                } else if (fname == "?*?") {
135                        value = arg1.first * arg2.first;
136                } else if (fname == "?/?") {
137                        value = arg1.first / arg2.first;
138                } else if (fname == "?%?") {
139                        value = arg1.first % arg2.first;
140                } else {
141                        valid = false;
142                }
143                // TODO: implement other intrinsic functions
144        }
145};
146
147std::pair<long long int, bool> eval(Expression * expr) {
148        PassVisitor<EvalOld> ev;
149        if (expr) {
150                expr->accept(ev);
151                return std::make_pair(ev.pass.value, ev.pass.valid);
152        } else {
153                return std::make_pair(0, false);
154        }
155}
156
157std::pair<long long int, bool> eval(const ast::Expr * expr) {
158        ast::Pass<EvalNew> ev;
159        if (expr) {
160                expr->accept(ev);
161                return std::make_pair(ev.pass.value, ev.pass.valid);
162        } else {
163                return std::make_pair(0, false);
164        }
165}
166
167// Local Variables: //
168// tab-width: 4 //
169// mode: c++ //
170// compile-command: "make install" //
171// End: //
Note: See TracBrowser for help on using the repository browser.