From 6ad953f877e969295e6c00af781849806dd7a093 Mon Sep 17 00:00:00 2001 From: ychenfo Date: Mon, 9 Aug 2021 01:43:41 +0800 Subject: [PATCH] top level class roughly handled, push for review --- nac3core/src/top_level.rs | 132 +++++++++++++++++++++++++++++++++- nac3core/src/typecheck/mod.rs | 2 +- 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/nac3core/src/top_level.rs b/nac3core/src/top_level.rs index d5a3276c..29238ee6 100644 --- a/nac3core/src/top_level.rs +++ b/nac3core/src/top_level.rs @@ -1,7 +1,8 @@ +use std::default; use std::{collections::HashMap, sync::Arc}; use super::typecheck::type_inferencer::PrimitiveStore; -use super::typecheck::typedef::{SharedUnifier, Type, Unifier}; +use super::typecheck::typedef::{SharedUnifier, Type, Unifier, TypeEnum}; use crate::symbol_resolver::SymbolResolver; use inkwell::{ basic_block::BasicBlock, builder::Builder, context::Context, module::Module, @@ -74,3 +75,132 @@ pub struct CodeGenContext<'ctx> { // the first one is the test_bb, and the second one is bb after the loop pub loop_bb: Option<(BasicBlock<'ctx>, BasicBlock<'ctx>)>, } + +pub struct TopLevelManager<'a> { + pub def_index: usize, + pub ctx: TopLevelContext, + pub resolver: &'a mut Box, + pub primitives: (PrimitiveStore, Unifier) +} + + +use rustpython_parser::ast; +impl<'a> TopLevelManager<'a> { + pub fn make_primitives() -> (PrimitiveStore, Unifier) { + let mut unifier = Unifier::new(); + let int32 = unifier.add_ty(TypeEnum::TObj { + obj_id: DefinitionId(0), // NOTE: what should it be? + fields: HashMap::new().into(), + params: HashMap::new(), + }); + let int64 = unifier.add_ty(TypeEnum::TObj { + obj_id: DefinitionId(1), // NOTE: what should it be? + fields: HashMap::new().into(), + params: HashMap::new(), + }); + let float = unifier.add_ty(TypeEnum::TObj { + obj_id: DefinitionId(2), // NOTE: what should it be? + fields: HashMap::new().into(), + params: HashMap::new(), + }); + let bool = unifier.add_ty(TypeEnum::TObj { + obj_id: DefinitionId(3), // NOTE: what should it be? + fields: HashMap::new().into(), + params: HashMap::new(), + }); + let none = unifier.add_ty(TypeEnum::TObj { + obj_id: DefinitionId(4), // NOTE: what should it be? + fields: HashMap::new().into(), + params: HashMap::new(), + }); + let primitives = PrimitiveStore { int32, int64, float, bool, none }; + crate::typecheck::magic_methods::set_primitives_magic_methods(&primitives, &mut unifier); + (primitives, unifier) + } + + pub fn new(resolver: &'a mut Box) -> Self { + TopLevelManager { + def_index: 1, + ctx: TopLevelContext { + definitions: Default::default(), + unifiers: Default::default() + }, + resolver, + primitives: Self::make_primitives() + } + } + + pub fn register_top_level(&mut self, ast: &ast::Stmt<()>) -> Result{ + match &ast.node { + ast::StmtKind::ClassDef { + name, + bases, + keywords, + body, + decorator_list + } => { + // ancestors and type_vars are found using the `bases` field + let mut class_ancestors: Vec = Default::default(); + let mut class_type_vars: Vec = Default::default(); + for base in bases { + match &base.node { + ast::ExprKind::Subscript {value, slice, ..} => { + match &value.node { + ast::ExprKind::Name {id, ..} if id == "Generic" => { + match &slice.node { + ast::ExprKind::Tuple {elts, ..} => { + for e in elts { + class_type_vars.push( + self.resolver. + parse_type_name(e) + .ok_or_else(|| "unkown base class type".to_string())? + ); // FIXME: is it correct to use this? + } + }, + _ => class_type_vars.push( + self.resolver + .parse_type_name(slice) + .ok_or_else(|| "unkown base class type".to_string())? + ) // FIXME: is it correct to use this? + } + }, + _ => return Err("only subscription on keyword Generic is allowed".into()) + } + }, + + ast::ExprKind::Name {id, ..} => { + class_ancestors.push(self.resolver.get_function_def(id)) // FIXME: is it correct to use this? + } + + _ => return Err("unsupported expression in the bases list".into()) + } + } + + // fields and methods are determined using the `body` field + let class_fields: Vec<(String, Type)> = Default::default(); + let class_methods: Vec<(String, Type, DefinitionId)> = Default::default(); + for stmt in body { + match &stmt.node { + ast::StmtKind::FunctionDef {name, .. } if name != "__init__" => { + let result = self.register_top_level(stmt)?; + unimplemented!() + }, + + _ => unimplemented!() + } + } + + let defs = self.ctx.definitions.write(); + let index = defs.len(); + + unimplemented!() + }, + + ast::StmtKind::FunctionDef {name, ..} => { + unimplemented!() + } + + _ => Err("only expect function definition and class definition".into()) + } + } +} \ No newline at end of file diff --git a/nac3core/src/typecheck/mod.rs b/nac3core/src/typecheck/mod.rs index a75222f5..db7bcaec 100644 --- a/nac3core/src/typecheck/mod.rs +++ b/nac3core/src/typecheck/mod.rs @@ -1,5 +1,5 @@ mod function_check; -mod magic_methods; +pub mod magic_methods; pub mod type_inferencer; pub mod typedef; mod unification_table;