diff 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
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/src/ast_type.rs
@@ -0,0 +1,225 @@
+use python_ast::{Module, Statement, Expr, BinOp};
+
+use std::collections::HashMap;
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+enum Type {
+    Top(usize),
+    Unit,
+    Bool,
+    Int,
+    Str,
+    Function(Vec<Type>, Vec<Type>),
+    Bottom
+}
+
+struct TypeVariable {
+    id: usize,
+    instance: Box<TypeVariable>,
+}
+
+trait Visitor<T> {
+    fn visit_module(&mut self, module: Module) -> T;
+    fn visit_statement(&mut self, statement: Statement) -> T;
+    fn visit_expr(&mut self, expr: Expr) -> T;
+}
+
+struct Typing {
+    environment: Vec<HashMap<String, Type>>,
+    next_id: usize,
+}
+
+impl Visitor<Type> for Typing {
+    fn visit_module(&mut self, module: Module) -> Type {
+        println!("{:?}", self.environment);
+        for statement in module.statements {
+            self.visit_statement(statement);
+        }
+        println!("{:?}", self.environment);
+        Type::Bottom
+    }
+
+    fn visit_statement(&mut self, statement: Statement) -> Type {
+        match statement {
+            Statement::FunctionDef(Expr::Name(name), arguments, body) => {
+                let mut env = self.environment.pop().unwrap();
+                self.environment.push(env.clone());
+
+                let nb_args = arguments.len();
+                for expr in arguments {
+                    let type_ = self.visit_expr(expr.clone());
+                    let name = match expr {
+                        Expr::Name(name) => name,
+                        _ => panic!()
+                    };
+                    env.insert(name.clone(), type_.clone());
+                }
+                self.environment.push(env);
+
+                for statement in body {
+                    self.visit_statement(statement);
+                }
+                self.environment.pop();
+
+                let mut types = Vec::with_capacity(nb_args);
+                for _ in 0..nb_args {
+                    self.next_id += 1;
+                    types.push(Type::Top(self.next_id));
+                }
+                Type::Bottom
+            },
+            Statement::FunctionDef(_, _, _) => {
+                println!("Statement:FunctionDef Error");
+                panic!()
+            },
+            Statement::Global(_) => {
+                Type::Bottom
+            },
+            Statement::If(test, body, orelse) => {
+                self.visit_expr(test);
+                for statement in body {
+                    self.visit_statement(statement);
+                }
+                for statement in orelse {
+                    self.visit_statement(statement);
+                }
+                Type::Bottom
+            },
+            Statement::Assign(targets, value) => {
+                let type_ = self.visit_expr(value);
+                if targets.len() != 1 {
+                    panic!();
+                }
+                println!("{:?}", self.environment.clone());
+                let mut env = self.environment.pop().unwrap();
+                for target in targets {
+                    let name = match target {
+                        Expr::Name(name) => name,
+                        _ => panic!()
+                    };
+                    println!("{} => {:?}", name, type_);
+                    env.insert(name, type_.clone());
+                }
+                self.environment.push(env);
+                println!("{:?}", self.environment.clone());
+                Type::Bottom
+            },
+            Statement::Return(expr) => {
+                self.visit_expr(expr)
+            },
+            Statement::ImportFrom(module, names) => {
+                for alias in names {
+                    self.visit_expr(alias);
+                }
+                Type::Bottom
+            },
+            Statement::Expr(expr) => {
+                self.visit_expr(expr)
+            },
+            Statement::Error => {
+                println!("Statement::Error");
+                panic!()
+            },
+        }
+    }
+
+    fn visit_expr(&mut self, expr: Expr) -> Type {
+        let expr_str = format!("{:?}", expr);
+        let type_ = match expr {
+            Expr::BinOp(left, op, right) => {
+                let type_left = self.visit_expr(*left);
+                let type_right = self.visit_expr(*right);
+
+                if op == BinOp::BinMult && type_left == Type::Str && type_right == Type::Int {
+                    return Type::Str;
+                }
+
+                if type_left != type_right {
+                    return Type::Bottom;
+                }
+                if op == BinOp::BinAdd || op == BinOp::BinMult {
+                    if type_left == Type::Int {
+                        Type::Int
+                    } else if type_left == Type::Str {
+                        Type::Str
+                    } else {
+                        Type::Bottom
+                    }
+                } else if op == BinOp::BinEq || op == BinOp::BinLt {
+                    Type::Bool
+                } else {
+                    Type::Bottom
+                }
+            },
+            Expr::Compare(_, _, _) => Type::Bool,
+            Expr::Call(func, args) => {
+                let func = *func;
+                let func = match func {
+                    Expr::Name(arg) => arg,
+                    _ => panic!()
+                };
+                let mut types = vec!();
+                for expr in args {
+                    let type_ = self.visit_expr(expr);
+                    types.push(type_);
+                }
+                println!("types: {:?}", types);
+                let env = match self.environment.pop() {
+                    Some(env) => env,
+                    None => return Type::Bottom
+                };
+                if env.contains_key(&func) {
+                    let value = env.get(&func).unwrap().clone();
+                    self.environment.push(env);
+                    value
+                } else {
+                    self.environment.push(env);
+                    Type::Bottom
+                }
+            },
+            Expr::Alias(_, _) => Type::Bottom,
+            Expr::Name(id) => {
+                let env = match self.environment.pop() {
+                    Some(env) => env,
+                    None => return Type::Bottom
+                };
+                if env.contains_key(&id) {
+                    let value = env.get(&id).unwrap().clone();
+                    self.environment.push(env);
+                    value
+                } else {
+                    self.environment.push(env);
+                    self.next_id += 1;
+                    Type::Top(self.next_id)
+                }
+            },
+            Expr::NameConstant(value) => {
+                if value == "True" || value == "False" {
+                    Type::Bool
+                } else if value == "None" {
+                    Type::Unit
+                } else {
+                    Type::Bottom
+                }
+            },
+            Expr::Str(_) => Type::Str,
+            Expr::Num(_) => Type::Int,
+            Expr::Error => {
+                println!("Expr::Error");
+                panic!()
+            }
+        };
+        println!("{} => {:?}", expr_str, type_);
+        type_
+    }
+}
+
+#[allow(dead_code)]
+pub fn type_ast(ast: Module) {
+    let mut environment = HashMap::new();
+    environment.insert("int".to_string(), Type::Int);
+    environment.insert("__name__".to_string(), Type::Str);
+    environment.insert("print".to_string(), Type::Unit);
+    let mut typing = Typing{environment: vec!(environment), next_id: 0};
+    typing.visit_module(ast);
+}