Start work on qualified names
This commit is contained in:
parent
89d967aee4
commit
34abb9b081
@ -46,6 +46,9 @@ pub enum Statement {
|
||||
pub type Block = Vec<Meta<Statement>>;
|
||||
pub type ParamName = Rc<String>;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct QualifiedName(pub Vec<Rc<String>>);
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct FormalParam {
|
||||
pub name: ParamName,
|
||||
@ -138,9 +141,9 @@ pub enum ExpressionKind {
|
||||
BinExp(BinOp, Box<Meta<Expression>>, Box<Meta<Expression>>),
|
||||
PrefixExp(PrefixOp, Box<Meta<Expression>>),
|
||||
TupleLiteral(Vec<Meta<Expression>>),
|
||||
Value(Rc<String>),
|
||||
Value(QualifiedName),
|
||||
NamedStruct {
|
||||
name: Rc<String>,
|
||||
name: QualifiedName,
|
||||
fields: Vec<(Rc<String>, Meta<Expression>)>,
|
||||
},
|
||||
Call {
|
||||
|
@ -85,13 +85,14 @@
|
||||
//! lambda_param_list := formal_param_list | formal_param
|
||||
//! paren_expr := "(" paren_inner ")"
|
||||
//! paren_inner := (expression ",")*
|
||||
//! identifier_expr := named_struct | IDENTIFIER
|
||||
//! identifier_expr := qualified_identifier | named_struct
|
||||
//! qualified_identifier := IDENTIFIER ("::" IDENTIFIER)*
|
||||
//! ```
|
||||
//!
|
||||
//! ## Literals
|
||||
//! ```text
|
||||
//! literal := "true" | "false" | number_literal | STR_LITERAL
|
||||
//! named_struct := IDENTIFIER record_block
|
||||
//! named_struct := qualified_identifier record_block
|
||||
//! record_block := "{" (record_entry, ",")* | "}" //TODO support anonymus structs, update syntax
|
||||
//! record_entry := IDENTIFIER ":" expression
|
||||
//! anonymous_struct := TODO
|
||||
@ -213,6 +214,7 @@ impl TokenHandler {
|
||||
fn peek(&mut self) -> Token {
|
||||
self.tokens.get(self.idx).map(|t: &Token| { t.clone()}).unwrap_or(Token { kind: TokenKind::EOF, line_num: self.end_of_file.0, char_num: self.end_of_file.1})
|
||||
}
|
||||
/// calling peek_n(0) is the same thing as peek()
|
||||
fn peek_n(&mut self, n: usize) -> Token {
|
||||
self.tokens.get(self.idx + n).map(|t: &Token| { t.clone()}).unwrap_or(Token { kind: TokenKind::EOF, line_num: self.end_of_file.0, char_num: self.end_of_file.1})
|
||||
}
|
||||
@ -757,16 +759,31 @@ impl Parser {
|
||||
#[recursive_descent_method]
|
||||
fn identifier_expr(&mut self) -> ParseResult<Expression> {
|
||||
use self::ExpressionKind::*;
|
||||
let identifier = self.identifier()?;
|
||||
let qualified_identifier = self.qualified_identifier()?;
|
||||
Ok(match self.token_handler.peek_kind() {
|
||||
LCurlyBrace if !self.restrictions.no_struct_literal => {
|
||||
let fields = self.record_block()?;
|
||||
Expression::new(NamedStruct { name: identifier, fields })
|
||||
Expression::new(NamedStruct { name: qualified_identifier, fields })
|
||||
},
|
||||
_ => Expression::new(Value(identifier))
|
||||
_ => Expression::new(Value(qualified_identifier))
|
||||
})
|
||||
}
|
||||
|
||||
#[recursive_descent_method]
|
||||
fn qualified_identifier(&mut self) -> ParseResult<QualifiedName> {
|
||||
let mut vec = vec![self.identifier()?];
|
||||
loop {
|
||||
match (self.token_handler.peek_kind(), self.token_handler.peek_kind_n(1)) {
|
||||
(Colon, Colon) => {
|
||||
self.token_handler.next(); self.token_handler.next();
|
||||
vec.push(self.identifier()?);
|
||||
},
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
Ok(QualifiedName(vec))
|
||||
}
|
||||
|
||||
#[recursive_descent_method]
|
||||
fn record_block(&mut self) -> ParseResult<Vec<(Rc<String>, Meta<Expression>)>> {
|
||||
Ok(
|
||||
|
@ -4,7 +4,7 @@ use std::str::FromStr;
|
||||
|
||||
use super::tokenize;
|
||||
use super::ParseResult;
|
||||
use crate::ast::{AST, Meta, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam, PrefixOp, BinOp};
|
||||
use crate::ast::{AST, Meta, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam, PrefixOp, BinOp, QualifiedName};
|
||||
use super::Statement::*;
|
||||
use super::Declaration::*;
|
||||
use super::Signature;
|
||||
@ -30,7 +30,7 @@ macro_rules! parse_error {
|
||||
($string:expr) => { assert!(parse($string).is_err()) }
|
||||
}
|
||||
macro_rules! val {
|
||||
($var:expr) => { Value(Rc::new($var.to_string())) }
|
||||
($var:expr) => { Value(QualifiedName(vec![Rc::new($var.to_string())])) };
|
||||
}
|
||||
macro_rules! ty {
|
||||
($name:expr) => { Singleton(tys!($name)) }
|
||||
@ -153,11 +153,11 @@ fn parsing_identifiers() {
|
||||
|
||||
parse_test!("None", AST(vec![exst!(val!("None"))]));
|
||||
parse_test!("Pandas { a: x + y }", AST(vec![
|
||||
exst!(NamedStruct { name: rc!(Pandas), fields: vec![(rc!(a), ex!(m binexp!("+", val!("x"), val!("y"))))]})
|
||||
exst!(NamedStruct { name: QualifiedName(vec![rc!(Pandas)]), fields: vec![(rc!(a), ex!(m binexp!("+", val!("x"), val!("y"))))]})
|
||||
]));
|
||||
parse_test! { "Pandas { a: n, b: q, }",
|
||||
AST(vec![
|
||||
exst!(NamedStruct { name: rc!(Pandas), fields:
|
||||
exst!(NamedStruct { name: QualifiedName(vec![rc!(Pandas)]), fields:
|
||||
vec![(rc!(a), ex!(m val!("n"))), (rc!(b), ex!(m val!("q")))]
|
||||
}
|
||||
)
|
||||
|
@ -16,7 +16,7 @@ use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::ast::*;
|
||||
use crate::symbol_table::{Symbol, SymbolSpec, SymbolTable};
|
||||
use crate::symbol_table::{Symbol, SymbolSpec, SymbolTable, ScopeSegment, ScopeSegmentKind, FullyQualifiedSymbolName};
|
||||
use crate::builtin::Builtin;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -142,6 +142,21 @@ impl InvocationArgument {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO this is incomplete
|
||||
fn lookup_name_in_scope(sym_name: &QualifiedName) -> FullyQualifiedSymbolName {
|
||||
let QualifiedName(vec) = sym_name;
|
||||
let len = vec.len();
|
||||
let new_vec: Vec<ScopeSegment> = vec.iter().enumerate().map(|(i, name)| {
|
||||
let kind = if i == (len - 1) {
|
||||
ScopeSegmentKind::Terminal
|
||||
} else {
|
||||
ScopeSegmentKind::Type
|
||||
};
|
||||
ScopeSegment { name: name.clone(), kind }
|
||||
}).collect();
|
||||
FullyQualifiedSymbolName(new_vec)
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
fn reduce(&self, symbol_table: &SymbolTable) -> Expr {
|
||||
use crate::ast::ExpressionKind::*;
|
||||
@ -153,14 +168,19 @@ impl Expression {
|
||||
BoolLiteral(b) => Expr::Lit(Lit::Bool(*b)),
|
||||
BinExp(binop, lhs, rhs) => binop.reduce(symbol_table, lhs, rhs),
|
||||
PrefixExp(op, arg) => op.reduce(symbol_table, arg),
|
||||
Value(name) => match symbol_table.lookup_by_name(name) {
|
||||
Some(Symbol { spec: SymbolSpec::DataConstructor { index, type_args, type_name}, .. }) => Expr::Constructor {
|
||||
type_name: type_name.clone(),
|
||||
name: name.clone(),
|
||||
tag: index.clone(),
|
||||
arity: type_args.len(),
|
||||
},
|
||||
_ => Expr::Sym(name.clone()),
|
||||
Value(qualified_name) => {
|
||||
let sym_name = lookup_name_in_scope(&qualified_name);
|
||||
let FullyQualifiedSymbolName(ref v) = sym_name;
|
||||
let name = v.last().unwrap().name.clone();
|
||||
match symbol_table.lookup_by_fqsn(&sym_name) {
|
||||
Some(Symbol { spec: SymbolSpec::DataConstructor { index, type_args, type_name}, .. }) => Expr::Constructor {
|
||||
type_name: type_name.clone(),
|
||||
name: name.clone(),
|
||||
tag: index.clone(),
|
||||
arity: type_args.len(),
|
||||
},
|
||||
_ => Expr::Sym(name.clone()),
|
||||
}
|
||||
},
|
||||
Call { f, arguments } => reduce_call_expression(f, arguments, symbol_table),
|
||||
TupleLiteral(exprs) => Expr::Tuple(exprs.iter().map(|e| e.node().reduce(symbol_table)).collect()),
|
||||
@ -183,8 +203,12 @@ fn reduce_lambda(params: &Vec<FormalParam>, body: &Block, symbol_table: &SymbolT
|
||||
})
|
||||
}
|
||||
|
||||
fn reduce_named_struct(name: &Rc<String>, fields: &Vec<(Rc<String>, Meta<Expression>)>, symbol_table: &SymbolTable) -> Expr {
|
||||
let (type_name, index, members_from_table) = match symbol_table.lookup_by_name(name) {
|
||||
fn reduce_named_struct(name: &QualifiedName, fields: &Vec<(Rc<String>, Meta<Expression>)>, symbol_table: &SymbolTable) -> Expr {
|
||||
|
||||
let sym_name = lookup_name_in_scope(name);
|
||||
let FullyQualifiedSymbolName(ref v) = sym_name;
|
||||
let ref name = v.last().unwrap().name;
|
||||
let (type_name, index, members_from_table) = match symbol_table.lookup_by_fqsn(&sym_name) {
|
||||
Some(Symbol { spec: SymbolSpec::RecordConstructor { members, type_name, index }, .. }) => (type_name.clone(), index, members),
|
||||
_ => return Expr::ReductionError("Not a record constructor".to_string()),
|
||||
};
|
||||
|
@ -26,8 +26,8 @@ impl fmt::Display for FullyQualifiedSymbolName {
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct ScopeSegment {
|
||||
name: Rc<String>, //TODO maybe this could be a &str, for efficiency?
|
||||
kind: ScopeSegmentKind,
|
||||
pub name: Rc<String>, //TODO maybe this could be a &str, for efficiency?
|
||||
pub kind: ScopeSegmentKind,
|
||||
}
|
||||
|
||||
impl fmt::Display for ScopeSegment {
|
||||
|
@ -412,10 +412,12 @@ impl<'a> TypeContext<'a> {
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
fn handle_value(&mut self, val: &Rc<String>) -> InferResult<Type> {
|
||||
match self.variable_map.lookup(val) {
|
||||
fn handle_value(&mut self, val: &QualifiedName) -> InferResult<Type> {
|
||||
let QualifiedName(vec) = val;
|
||||
let var = &vec[0];
|
||||
match self.variable_map.lookup(var) {
|
||||
Some(ty) => Ok(ty.clone()),
|
||||
None => TypeError::new(format!("Couldn't find variable: {}", val))
|
||||
None => TypeError::new(format!("Couldn't find variable: {}", &var)),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user