Mercurial > python-compiler.rs
comparison src/ast_type.rs @ 0:211b0df72e64
Hello world!
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sun, 29 May 2016 19:15:02 +0100 |
parents | |
children | 5fc7c2790d8c |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:211b0df72e64 |
---|---|
1 use python_ast::{Module, Statement, Expr, BinOp}; | |
2 | |
3 use std::collections::HashMap; | |
4 | |
5 #[derive(Clone, Debug, PartialEq, Eq)] | |
6 enum Type { | |
7 Top(usize), | |
8 Unit, | |
9 Bool, | |
10 Int, | |
11 Str, | |
12 Function(Vec<Type>, Vec<Type>), | |
13 Bottom | |
14 } | |
15 | |
16 struct TypeVariable { | |
17 id: usize, | |
18 instance: Box<TypeVariable>, | |
19 } | |
20 | |
21 trait Visitor<T> { | |
22 fn visit_module(&mut self, module: Module) -> T; | |
23 fn visit_statement(&mut self, statement: Statement) -> T; | |
24 fn visit_expr(&mut self, expr: Expr) -> T; | |
25 } | |
26 | |
27 struct Typing { | |
28 environment: Vec<HashMap<String, Type>>, | |
29 next_id: usize, | |
30 } | |
31 | |
32 impl Visitor<Type> for Typing { | |
33 fn visit_module(&mut self, module: Module) -> Type { | |
34 println!("{:?}", self.environment); | |
35 for statement in module.statements { | |
36 self.visit_statement(statement); | |
37 } | |
38 println!("{:?}", self.environment); | |
39 Type::Bottom | |
40 } | |
41 | |
42 fn visit_statement(&mut self, statement: Statement) -> Type { | |
43 match statement { | |
44 Statement::FunctionDef(Expr::Name(name), arguments, body) => { | |
45 let mut env = self.environment.pop().unwrap(); | |
46 self.environment.push(env.clone()); | |
47 | |
48 let nb_args = arguments.len(); | |
49 for expr in arguments { | |
50 let type_ = self.visit_expr(expr.clone()); | |
51 let name = match expr { | |
52 Expr::Name(name) => name, | |
53 _ => panic!() | |
54 }; | |
55 env.insert(name.clone(), type_.clone()); | |
56 } | |
57 self.environment.push(env); | |
58 | |
59 for statement in body { | |
60 self.visit_statement(statement); | |
61 } | |
62 self.environment.pop(); | |
63 | |
64 let mut types = Vec::with_capacity(nb_args); | |
65 for _ in 0..nb_args { | |
66 self.next_id += 1; | |
67 types.push(Type::Top(self.next_id)); | |
68 } | |
69 Type::Bottom | |
70 }, | |
71 Statement::FunctionDef(_, _, _) => { | |
72 println!("Statement:FunctionDef Error"); | |
73 panic!() | |
74 }, | |
75 Statement::Global(_) => { | |
76 Type::Bottom | |
77 }, | |
78 Statement::If(test, body, orelse) => { | |
79 self.visit_expr(test); | |
80 for statement in body { | |
81 self.visit_statement(statement); | |
82 } | |
83 for statement in orelse { | |
84 self.visit_statement(statement); | |
85 } | |
86 Type::Bottom | |
87 }, | |
88 Statement::Assign(targets, value) => { | |
89 let type_ = self.visit_expr(value); | |
90 if targets.len() != 1 { | |
91 panic!(); | |
92 } | |
93 println!("{:?}", self.environment.clone()); | |
94 let mut env = self.environment.pop().unwrap(); | |
95 for target in targets { | |
96 let name = match target { | |
97 Expr::Name(name) => name, | |
98 _ => panic!() | |
99 }; | |
100 println!("{} => {:?}", name, type_); | |
101 env.insert(name, type_.clone()); | |
102 } | |
103 self.environment.push(env); | |
104 println!("{:?}", self.environment.clone()); | |
105 Type::Bottom | |
106 }, | |
107 Statement::Return(expr) => { | |
108 self.visit_expr(expr) | |
109 }, | |
110 Statement::ImportFrom(module, names) => { | |
111 for alias in names { | |
112 self.visit_expr(alias); | |
113 } | |
114 Type::Bottom | |
115 }, | |
116 Statement::Expr(expr) => { | |
117 self.visit_expr(expr) | |
118 }, | |
119 Statement::Error => { | |
120 println!("Statement::Error"); | |
121 panic!() | |
122 }, | |
123 } | |
124 } | |
125 | |
126 fn visit_expr(&mut self, expr: Expr) -> Type { | |
127 let expr_str = format!("{:?}", expr); | |
128 let type_ = match expr { | |
129 Expr::BinOp(left, op, right) => { | |
130 let type_left = self.visit_expr(*left); | |
131 let type_right = self.visit_expr(*right); | |
132 | |
133 if op == BinOp::BinMult && type_left == Type::Str && type_right == Type::Int { | |
134 return Type::Str; | |
135 } | |
136 | |
137 if type_left != type_right { | |
138 return Type::Bottom; | |
139 } | |
140 if op == BinOp::BinAdd || op == BinOp::BinMult { | |
141 if type_left == Type::Int { | |
142 Type::Int | |
143 } else if type_left == Type::Str { | |
144 Type::Str | |
145 } else { | |
146 Type::Bottom | |
147 } | |
148 } else if op == BinOp::BinEq || op == BinOp::BinLt { | |
149 Type::Bool | |
150 } else { | |
151 Type::Bottom | |
152 } | |
153 }, | |
154 Expr::Compare(_, _, _) => Type::Bool, | |
155 Expr::Call(func, args) => { | |
156 let func = *func; | |
157 let func = match func { | |
158 Expr::Name(arg) => arg, | |
159 _ => panic!() | |
160 }; | |
161 let mut types = vec!(); | |
162 for expr in args { | |
163 let type_ = self.visit_expr(expr); | |
164 types.push(type_); | |
165 } | |
166 println!("types: {:?}", types); | |
167 let env = match self.environment.pop() { | |
168 Some(env) => env, | |
169 None => return Type::Bottom | |
170 }; | |
171 if env.contains_key(&func) { | |
172 let value = env.get(&func).unwrap().clone(); | |
173 self.environment.push(env); | |
174 value | |
175 } else { | |
176 self.environment.push(env); | |
177 Type::Bottom | |
178 } | |
179 }, | |
180 Expr::Alias(_, _) => Type::Bottom, | |
181 Expr::Name(id) => { | |
182 let env = match self.environment.pop() { | |
183 Some(env) => env, | |
184 None => return Type::Bottom | |
185 }; | |
186 if env.contains_key(&id) { | |
187 let value = env.get(&id).unwrap().clone(); | |
188 self.environment.push(env); | |
189 value | |
190 } else { | |
191 self.environment.push(env); | |
192 self.next_id += 1; | |
193 Type::Top(self.next_id) | |
194 } | |
195 }, | |
196 Expr::NameConstant(value) => { | |
197 if value == "True" || value == "False" { | |
198 Type::Bool | |
199 } else if value == "None" { | |
200 Type::Unit | |
201 } else { | |
202 Type::Bottom | |
203 } | |
204 }, | |
205 Expr::Str(_) => Type::Str, | |
206 Expr::Num(_) => Type::Int, | |
207 Expr::Error => { | |
208 println!("Expr::Error"); | |
209 panic!() | |
210 } | |
211 }; | |
212 println!("{} => {:?}", expr_str, type_); | |
213 type_ | |
214 } | |
215 } | |
216 | |
217 #[allow(dead_code)] | |
218 pub fn type_ast(ast: Module) { | |
219 let mut environment = HashMap::new(); | |
220 environment.insert("int".to_string(), Type::Int); | |
221 environment.insert("__name__".to_string(), Type::Str); | |
222 environment.insert("print".to_string(), Type::Unit); | |
223 let mut typing = Typing{environment: vec!(environment), next_id: 0}; | |
224 typing.visit_module(ast); | |
225 } |