-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathexprflow.h
138 lines (123 loc) · 5.4 KB
/
exprflow.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#pragma once
#include "semantics.h"
#include "lexer.h"
#include "parser.h"
#include "codegen.h"
#include "run_test.h"
#include "exprfndef.h"
struct CgValue;
struct ExprFlow:Expr{ // control flow statements
};
/// if-else expression.
struct ExprIf : ExprFlow {
Scope* scope=0;
Expr* cond=0;
Expr* body=0;
Expr* else_block=0;
void dump(PrinterRef depth) const;
ExprIf(const SrcPos& s){pos=s;name=0;cond=0;body=0;else_block=0;}
~ExprIf(){}
Node* clone() const;
bool is_undefined()const {
if (cond)if (cond->is_undefined()) return true;
if (body)if (body->is_undefined()) return true;
if (else_block)if (else_block->is_undefined()) return true;
return false;
}
const char* kind_str()const override {return"if";}
ResolveResult resolve(Scope* scope,const Type*,int flags) ;
void find_vars_written(Scope* s,set<Variable*>& vars ) const override;
void translate_tparams(const TParamXlat& tpx) override;
CgValue compile(CodeGen& cg, Scope* sc,CgValue input) override;
Scope* get_scope() override {return this->scope;}
void recurse(std::function<void(Node*)>& f)override;
};
/// For-Else loop/expression. Currrently the lowest level loop construct
/// implement other styles of loop as specializations that omit init, incr etc.
struct ExprFor : ExprFlow {
ExprFor(){}
Expr* init=0; // clike initializer or deduced from pattern/expr
Expr* cond=0; // C-like condition, or deduced from pattern/expr
Expr* incr=0; // clike increment, or deduced from patter/expr
Expr* body=0;
Expr* else_block=0; // run if the loop exits without break.
Scope* scope=0;
void dump(PrinterRef depth) const;
ExprFor(const SrcPos& s) {pos=s;name=0;init=0;cond=0;incr=0;body=0;else_block=0;scope=0;}
//bool is_c_for()const {return !pattern;}
//bool is_for_in()const {return pattern && cond==0 && incr==0;}
~ExprFor(){}
const char* kind_str()const override {return"for";}
bool is_undefined()const {return /*(pattern&&pattern->is_undefined())||*/(init &&init->is_undefined())||(cond&&cond->is_undefined())||(incr&&incr->is_undefined())||(body&& body->is_undefined())||(else_block&&else_block->is_undefined());}
Expr* find_next_break_expr(Expr* prev=0);
Node* clone()const;
Node* clone_for_sub(ExprFor* f)const;
Scope* get_scope()override {return this->scope;}
ExprFor* as_for()override {return this;}
ResolveResult resolve(Scope* scope,const Type*,int flags) override;
ResolveResult resolve_for_sub(Scope* scope,const Type*,int flags);
void find_vars_written(Scope* s,set<Variable*>& vars ) const override;
void translate_tparams(const TParamXlat& tpx) override;
CgValue compile(CodeGen&, Scope*,CgValue) override;
Expr* loop_else_block()const override{return else_block;}
void recurse(std::function<void(Node*)>& f)override;
};
struct ExprForIn : ExprFor{
ExprForIn(){};
ExprForIn(SrcPos p){pos=p;};
Pattern* pattern=nullptr; // iterator
Expr* expr=nullptr;
Node* clone()const override;
const char* kind_str()const override{return "for_in";}
void translate_tparams(const TParamXlat& tpx) override;
ResolveResult resolve(Scope* scope,const Type*,int flags) override;
};
/// rust match, doesn't work yet - unlikely to support everything it does
/// C++ featureset extended with 2way inference can emulate match like boost variant but improved.
struct ExprMatch : ExprFlow {
Scope* scope=0;
const char* kind_str() const override{return "match";}
CgValue compile(CodeGen& cg, Scope* sc,CgValue input) override;
ResolveResult resolve(Scope* sc, const Type* desired, int flags);
Expr* expr=0;
MatchArm* arms=0;
Node* clone()const{ return this->clone_into(new ExprMatch);}
Node* clone_into(ExprMatch* ) const;
void dump(PrinterRef depth)const;
void recurse(std::function<void(Node*)>& f)override;
};
struct MatchArm : ExprScopeBlock {
/// if match expr satisfies the pattern,
/// binds variables from the pattern & executes 'expr'
ExprMatch* match_owner;
Scope* scope=0;
Pattern* pattern=0;
Expr* cond=0;
Expr* body=0;
MatchArm* next=0;
void dump(PrinterRef depth)const;
Node* clone() const override;
Scope* get_scope()override{return this->scope;}
void translate_tparams(const TParamXlat& tpx){}
CgValue compile_condition(CodeGen& cg, Scope* sc, const Pattern* match_expr,CgValue match_val);
// todo - as patterns exist elsewhere, so 'compile-bind might generalize'.
CgValue compile_bind_locals(CodeGen& cg, Scope* sc, const Pattern* match_expr,CgValue match_val);
CgValue compile(CodeGen& cg, Scope* sc, CgValue input) override;
// ResolveResult resolve(Scope* sc, const Type* desired, int flags); doesn't have resolve method because it takes 2 inputs.
void recurse(std::function<void(Node*)>& f) override;
const char* kind_str() const override {return "match_arm";}
};
struct ExprIfLet : ExprMatch{ // sugar for match 1arm. parses+prints different. eval the same
void dump(PrinterRef depth)const;
Node* clone() const override {return this->clone_into(new ExprIfLet);}
const char* kind_str() const override {return "if_let";}
ExprIfLet(){};
ExprIfLet(SrcPos p,Pattern* ptn, Expr* _expr, Expr* _body, Expr* _else);
};
struct ExprWhileLet : ExprFor{ // from rust, alternate sugar for destructuring assignment loop.
//void dump(int depth)const;
//Node* clone() const override {return this->clone_into(new ExprIfLet);}
const char* kind_str() const override{return "while_let";}
ResolveResult resolve(Scope* sc, const Type* desired, int flags);
CgValue compile(CodeGen& cg, Scope* sc,CgValue input);
};