forked from M-Labs/nac3
ownwership and none type
This commit is contained in:
parent
1cc4c3f8d4
commit
a439ce61f7
@ -1,13 +1,13 @@
|
|||||||
use crate::inference::resolve_call;
|
use crate::inference::resolve_call;
|
||||||
|
use crate::operators::*;
|
||||||
use crate::primitives::*;
|
use crate::primitives::*;
|
||||||
use crate::typedef::{GlobalContext, Type, Type::*};
|
use crate::typedef::{GlobalContext, Type, Type::*};
|
||||||
use rustpython_parser::ast::{Expression, ExpressionType};
|
use rustpython_parser::ast::{Comparison, Expression, ExpressionType, Operator, UnaryOperator};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryFrom;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
type SymTable<'a> = HashMap<&'a str, Rc<Type>>;
|
type SymTable<'a> = HashMap<&'a str, Rc<Type>>;
|
||||||
type ParserResult = Result<Rc<Type>, String>;
|
type ParserResult = Result<Option<Rc<Type>>, String>;
|
||||||
|
|
||||||
pub fn parse_expr(ctx: &GlobalContext, sym_table: &SymTable, expr: &Expression) -> ParserResult {
|
pub fn parse_expr(ctx: &GlobalContext, sym_table: &SymTable, expr: &Expression) -> ParserResult {
|
||||||
Err("not supported".into())
|
Err("not supported".into())
|
||||||
@ -22,7 +22,7 @@ fn parse_constant(
|
|||||||
match value {
|
match value {
|
||||||
Number::Integer { .. } => {
|
Number::Integer { .. } => {
|
||||||
// not check the range now
|
// not check the range now
|
||||||
Ok(PrimitiveType(INT32_TYPE).into())
|
Ok(Some(PrimitiveType(INT32_TYPE).into()))
|
||||||
// if i32::try_from(&value).is_ok() {
|
// if i32::try_from(&value).is_ok() {
|
||||||
// Ok(PrimitiveType(INT32_TYPE).into())
|
// Ok(PrimitiveType(INT32_TYPE).into())
|
||||||
// } else if i64::try_from(&value).is_ok() {
|
// } else if i64::try_from(&value).is_ok() {
|
||||||
@ -31,40 +31,47 @@ fn parse_constant(
|
|||||||
// Err("integer out of range".into())
|
// Err("integer out of range".into())
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
Number::Float { .. } => Ok(PrimitiveType(FLOAT_TYPE).into()),
|
Number::Float { .. } => Ok(Some(PrimitiveType(FLOAT_TYPE).into())),
|
||||||
_ => Err("not supported".into()),
|
_ => Err("not supported".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_identifier(_: &GlobalContext, sym_table: &SymTable, name: &str) -> ParserResult {
|
fn parse_identifier(_: &GlobalContext, sym_table: &SymTable, name: &str) -> ParserResult {
|
||||||
match sym_table.get(name) {
|
match sym_table.get(name) {
|
||||||
Some(v) => Ok(v.clone()),
|
Some(v) => Ok(Some(v.clone())),
|
||||||
None => Err("unbounded variable".into()),
|
None => Err("unbounded variable".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_list(ctx: &GlobalContext, sym_table: &SymTable, elements: &[Expression]) -> ParserResult {
|
fn parse_list(ctx: &GlobalContext, sym_table: &SymTable, elements: &[Expression]) -> ParserResult {
|
||||||
if elements.len() == 0 {
|
if elements.len() == 0 {
|
||||||
return Ok(ParametricType(LIST_TYPE, vec![BotType.into()]).into());
|
return Ok(Some(ParametricType(LIST_TYPE, vec![BotType.into()]).into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut types = elements.iter().map(|v| parse_expr(&ctx, sym_table, v));
|
let mut types = elements.iter().map(|v| parse_expr(&ctx, sym_table, v));
|
||||||
|
|
||||||
let head = types.next().unwrap()?;
|
let head = types.next().unwrap()?;
|
||||||
|
if head.is_none() {
|
||||||
|
return Err("list elements must have some type".into());
|
||||||
|
}
|
||||||
for v in types {
|
for v in types {
|
||||||
if v? != head {
|
if v? != head {
|
||||||
return Err("inhomogeneous list is not allowed".into());
|
return Err("inhomogeneous list is not allowed".into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(ParametricType(LIST_TYPE, vec![head]).into())
|
Ok(Some(ParametricType(LIST_TYPE, vec![head.unwrap()]).into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_tuple(ctx: &GlobalContext, sym_table: &SymTable, elements: &[Expression]) -> ParserResult {
|
fn parse_tuple(ctx: &GlobalContext, sym_table: &SymTable, elements: &[Expression]) -> ParserResult {
|
||||||
let types: Result<Vec<_>, String> = elements
|
let types: Result<Option<Vec<_>>, String> = elements
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| parse_expr(&ctx, sym_table, v))
|
.map(|v| parse_expr(&ctx, sym_table, v))
|
||||||
.collect();
|
.collect();
|
||||||
Ok(ParametricType(TUPLE_TYPE, types?).into())
|
if let Some(t) = types? {
|
||||||
|
Ok(Some(ParametricType(TUPLE_TYPE, t).into()))
|
||||||
|
} else {
|
||||||
|
Err("tuple elements must have some type".into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_attribute(
|
fn parse_attribute(
|
||||||
@ -73,7 +80,7 @@ fn parse_attribute(
|
|||||||
value: &Expression,
|
value: &Expression,
|
||||||
name: String,
|
name: String,
|
||||||
) -> ParserResult {
|
) -> ParserResult {
|
||||||
let value = parse_expr(ctx, sym_table, value)?;
|
let value = parse_expr(ctx, sym_table, value)?.ok_or("no value".to_string())?;
|
||||||
if let TypeVariable(id) = value.as_ref() {
|
if let TypeVariable(id) = value.as_ref() {
|
||||||
let v = ctx.get_variable(*id);
|
let v = ctx.get_variable(*id);
|
||||||
if v.bound.len() == 0 {
|
if v.bound.len() == 0 {
|
||||||
@ -91,12 +98,12 @@ fn parse_attribute(
|
|||||||
return Err("unknown field (type mismatch between variants)".into());
|
return Err("unknown field (type mismatch between variants)".into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(ty.unwrap().clone());
|
return Ok(Some(ty.unwrap().clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
match value.get_base(ctx) {
|
match value.get_base(ctx) {
|
||||||
Some(b) => match b.fields.get(name.as_str()) {
|
Some(b) => match b.fields.get(name.as_str()) {
|
||||||
Some(t) => Ok(t.clone()),
|
Some(t) => Ok(Some(t.clone())),
|
||||||
None => Err("no such field".into()),
|
None => Err("no such field".into()),
|
||||||
},
|
},
|
||||||
None => Err("this object has no fields".into()),
|
None => Err("this object has no fields".into()),
|
||||||
@ -109,15 +116,28 @@ fn parse_bool_ops(
|
|||||||
values: &[Expression],
|
values: &[Expression],
|
||||||
) -> ParserResult {
|
) -> ParserResult {
|
||||||
assert_eq!(values.len(), 2);
|
assert_eq!(values.len(), 2);
|
||||||
let left = parse_expr(ctx, sym_table, &values[0])?;
|
let left = parse_expr(ctx, sym_table, &values[0])?.ok_or("no value".to_string())?;
|
||||||
let right = parse_expr(ctx, sym_table, &values[1])?;
|
let right = parse_expr(ctx, sym_table, &values[1])?.ok_or("no value".to_string())?;
|
||||||
|
|
||||||
let b = PrimitiveType(BOOL_TYPE);
|
let b = PrimitiveType(BOOL_TYPE);
|
||||||
if left.as_ref() == &b && right.as_ref() == &b {
|
if left.as_ref() == &b && right.as_ref() == &b {
|
||||||
Ok(b.into())
|
Ok(Some(b.into()))
|
||||||
} else {
|
} else {
|
||||||
Err("bool operands must be bool".into())
|
Err("bool operands must be bool".into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_bin_ops(
|
||||||
|
ctx: &GlobalContext,
|
||||||
|
sym_table: &SymTable,
|
||||||
|
op: &Operator,
|
||||||
|
left: &Expression,
|
||||||
|
right: &Expression,
|
||||||
|
) -> ParserResult {
|
||||||
|
let left = parse_expr(ctx, sym_table, left)?.ok_or("no value".to_string())?;
|
||||||
|
let right = parse_expr(ctx, sym_table, right)?.ok_or("no value".to_string())?;
|
||||||
|
let fun = binop_name(op);
|
||||||
|
let mut assumptions = HashMap::new();
|
||||||
|
resolve_call(ctx, Some(left), fun, &[right], &mut assumptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use rustpython_parser::ast::{Comparison, Operator, UnaryOperator};
|
use rustpython_parser::ast::{Comparison, Operator, UnaryOperator};
|
||||||
|
|
||||||
pub fn binop_name(op: Operator) -> &'static str {
|
pub fn binop_name(op: &Operator) -> &'static str {
|
||||||
match op {
|
match op {
|
||||||
Operator::Add => "add",
|
Operator::Add => "add",
|
||||||
Operator::Sub => "sub",
|
Operator::Sub => "sub",
|
||||||
@ -18,7 +18,7 @@ pub fn binop_name(op: Operator) -> &'static str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unaryop_name(op: UnaryOperator) -> &'static str {
|
pub fn unaryop_name(op: &UnaryOperator) -> &'static str {
|
||||||
match op {
|
match op {
|
||||||
UnaryOperator::Pos => "pos",
|
UnaryOperator::Pos => "pos",
|
||||||
UnaryOperator::Neg => "neg",
|
UnaryOperator::Neg => "neg",
|
||||||
@ -27,7 +27,7 @@ pub fn unaryop_name(op: UnaryOperator) -> &'static str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn comparison_name(op: Comparison) -> Option<&'static str> {
|
pub fn comparison_name(op: &Comparison) -> Option<&'static str> {
|
||||||
match op {
|
match op {
|
||||||
Comparison::Less => Some("lt"),
|
Comparison::Less => Some("lt"),
|
||||||
Comparison::LessOrEqual => Some("le"),
|
Comparison::LessOrEqual => Some("le"),
|
||||||
|
Loading…
Reference in New Issue
Block a user