handle impl block

This commit is contained in:
Greg Shuflin 2021-12-07 02:39:01 -08:00
parent b778428e98
commit b5ec8116a2
11 changed files with 183 additions and 66 deletions

View File

@ -18,6 +18,7 @@ use crate::{
derivative::Derivative, derivative::Derivative,
identifier::{define_id_kind, Id}, identifier::{define_id_kind, Id},
parsing::Location, parsing::Location,
util::delim_wrapped,
}; };
define_id_kind!(ASTItem); define_id_kind!(ASTItem);
@ -40,12 +41,12 @@ impl fmt::Display for AST {
#[derive(Derivative, Debug, Clone)] #[derive(Derivative, Debug, Clone)]
#[derivative(PartialEq)] #[derivative(PartialEq)]
pub struct Statement { pub struct Statement<K> {
#[derivative(PartialEq = "ignore")] #[derivative(PartialEq = "ignore")]
pub id: ItemId, pub id: ItemId,
#[derivative(PartialEq = "ignore")] #[derivative(PartialEq = "ignore")]
pub location: Location, pub location: Location,
pub kind: StatementKind, pub kind: K,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -65,23 +66,23 @@ pub enum FlowControl {
#[derive(Debug, Clone, PartialEq, Default)] #[derive(Debug, Clone, PartialEq, Default)]
pub struct Block { pub struct Block {
pub statements: Vec<Statement>, pub statements: Vec<Statement<StatementKind>>,
} }
impl From<Vec<Statement>> for Block { impl From<Vec<Statement<StatementKind>>> for Block {
fn from(statements: Vec<Statement>) -> Self { fn from(statements: Vec<Statement<StatementKind>>) -> Self {
Self { statements } Self { statements }
} }
} }
impl From<Statement> for Block { impl From<Statement<StatementKind>> for Block {
fn from(statement: Statement) -> Self { fn from(statement: Statement<StatementKind>) -> Self {
Self { statements: vec![statement] } Self { statements: vec![statement] }
} }
} }
impl AsRef<[Statement]> for Block { impl AsRef<[Statement<StatementKind>]> for Block {
fn as_ref(&self) -> &[Statement] { fn as_ref(&self) -> &[Statement<StatementKind>] {
self.statements.as_ref() self.statements.as_ref()
} }
} }
@ -123,15 +124,41 @@ pub struct FormalParam {
pub enum Declaration { pub enum Declaration {
FuncSig(Signature), FuncSig(Signature),
FuncDecl(Signature, Block), FuncDecl(Signature, Block),
TypeDecl { name: TypeSingletonName, body: TypeBody, mutable: bool }, TypeDecl {
name: TypeSingletonName,
body: TypeBody,
mutable: bool,
},
//TODO TypeAlias `original` needs to be a more complex type definition //TODO TypeAlias `original` needs to be a more complex type definition
TypeAlias { alias: Rc<String>, original: Rc<String> }, TypeAlias {
Binding { name: Rc<String>, constant: bool, type_anno: Option<TypeIdentifier>, expr: Expression }, alias: Rc<String>,
Impl { type_name: TypeIdentifier, interface_name: Option<TypeSingletonName>, block: Vec<Declaration> }, original: Rc<String>,
Interface { name: Rc<String>, signatures: Vec<Signature> }, },
Binding {
name: Rc<String>,
constant: bool,
type_anno: Option<TypeIdentifier>,
expr: Expression,
},
Impl {
type_name: TypeIdentifier,
interface_name: Option<TypeSingletonName>,
block: Vec<Statement<Declaration>>,
},
Interface {
name: Rc<String>,
signatures: Vec<Signature>,
},
//TODO need to limit the types of statements that can be annotated //TODO need to limit the types of statements that can be annotated
Annotation { name: Rc<String>, arguments: Vec<Expression>, inner: Box<Statement> }, Annotation {
Module { name: Rc<String>, items: Block }, name: Rc<String>,
arguments: Vec<Expression>,
inner: Box<Statement<StatementKind>>,
},
Module {
name: Rc<String>,
items: Block,
},
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -192,6 +219,22 @@ pub enum TypeIdentifier {
Singleton(TypeSingletonName), Singleton(TypeSingletonName),
} }
impl fmt::Display for TypeIdentifier {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TypeIdentifier::Tuple(items) =>
write!(f, "{}", delim_wrapped('(', ')', items.iter().map(|item| item.to_string()))),
TypeIdentifier::Singleton(tsn) => {
write!(f, "{}", tsn.name)?;
if !tsn.params.is_empty() {
write!(f, "{}", delim_wrapped('<', '>', tsn.params.iter().map(|item| item.to_string())))?;
}
Ok(())
}
}
}
}
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct TypeSingletonName { pub struct TypeSingletonName {
pub name: Rc<String>, pub name: Rc<String>,

View File

@ -29,7 +29,7 @@ pub(super) fn render_ast(ast: &AST) -> String {
buf buf
} }
fn render_statement(stmt: &Statement, indent: usize, buf: &mut String) { fn render_statement(stmt: &Statement<StatementKind>, indent: usize, buf: &mut String) {
use StatementKind::*; use StatementKind::*;
do_indent(indent, buf); do_indent(indent, buf);
match stmt.kind { match stmt.kind {

View File

@ -163,7 +163,7 @@ pub fn block(input: Span) -> ParseResult<Block> {
context("block", map(block_template(many1(statement_delimiter), statement), |items| items.into()))(input) context("block", map(block_template(many1(statement_delimiter), statement), |items| items.into()))(input)
} }
fn statement(input: Span) -> ParseResult<Statement> { fn statement(input: Span) -> ParseResult<Statement<StatementKind>> {
let (input, pos) = position(input)?; let (input, pos) = position(input)?;
let location = pos.location_offset().into(); let location = pos.location_offset().into();
let id = fresh_id(&input); let id = fresh_id(&input);
@ -243,8 +243,16 @@ fn implementation(input: Span) -> ParseResult<Declaration> {
))(input) ))(input)
} }
fn decl_block(input: Span) -> ParseResult<Vec<Declaration>> { fn decl_block(input: Span) -> ParseResult<Vec<Statement<Declaration>>> {
block_template(many1(statement_delimiter), func_decl)(input) context("decl-block", block_template(many1(statement_delimiter), func_decl_statement))(input)
}
fn func_decl_statement(input: Span) -> ParseResult<Statement<Declaration>> {
let (input, pos) = position(input)?;
let location = pos.location_offset().into();
let id = fresh_id(&input);
let (rest, kind) = context("decl-statement", func_decl)(input)?;
Ok((rest, Statement { id, location, kind }))
} }
fn interface(input: Span) -> ParseResult<Declaration> { fn interface(input: Span) -> ParseResult<Declaration> {

View File

@ -38,10 +38,10 @@ peg::parser! {
"{" __ items:(statement(parser) ** delimiter()) delimiter()? __ "}" { items.into() } / "{" __ items:(statement(parser) ** delimiter()) delimiter()? __ "}" { items.into() } /
"{" __ stmt:statement(parser) __ "}" { vec![stmt].into() } "{" __ stmt:statement(parser) __ "}" { vec![stmt].into() }
rule block_item(parser: &mut Parser) -> Statement = rule block_item(parser: &mut Parser) -> Statement<StatementKind> =
_ stmt:statement(parser) _ delimiter()+ { stmt } _ stmt:statement(parser) _ delimiter()+ { stmt }
rule statement(parser: &mut Parser) -> Statement = rule statement(parser: &mut Parser) -> Statement<StatementKind> =
_ pos:position!() kind:statement_kind(parser) _ { Statement { id: parser.fresh(), location: pos.into(), kind } } _ pos:position!() kind:statement_kind(parser) _ { Statement { id: parser.fresh(), location: pos.into(), kind } }
rule statement_kind(parser: &mut Parser) -> StatementKind = rule statement_kind(parser: &mut Parser) -> StatementKind =
@ -100,8 +100,11 @@ peg::parser! {
Declaration::Impl { type_name, interface_name: None, block } Declaration::Impl { type_name, interface_name: None, block }
} }
rule decl_block(parser: &mut Parser) -> Vec<Declaration> = rule decl_block(parser: &mut Parser) -> Vec<Statement<Declaration>> =
"{" __ decls:(func_declaration(parser) ** (delimiter()+)) delimiter()? __ "}" { decls } "{" __ decls:(func_declaration_stmt(parser) ** (delimiter()+)) delimiter()? __ "}" { decls }
rule func_declaration_stmt(parser: &mut Parser) -> Statement<Declaration> =
pos:position!() decl:func_declaration(parser) { Statement { id: parser.fresh(), location: pos.into(), kind: decl } }
rule interface(parser: &mut Parser) -> Declaration = rule interface(parser: &mut Parser) -> Declaration =
"interface" _ name:identifier() _ signatures:signature_block(parser) { Declaration::Interface { name: rc_string(name), signatures } } "interface" _ name:identifier() _ signatures:signature_block(parser) { Declaration::Interface { name: rc_string(name), signatures } }

View File

@ -21,11 +21,11 @@ fn strlit(s: &str) -> ExpressionKind {
ExpressionKind::StringLiteral { s: Rc::new(s.to_string()), prefix: None } ExpressionKind::StringLiteral { s: Rc::new(s.to_string()), prefix: None }
} }
fn stmt(kind: StatementKind) -> Statement { fn stmt<K>(kind: K) -> Statement<K> {
Statement { location: Location::default(), id: ItemId::default(), kind } Statement { location: Location::default(), id: ItemId::default(), kind }
} }
fn exst(kind: ExpressionKind) -> Statement { fn exst(kind: ExpressionKind) -> Statement<StatementKind> {
Statement { Statement {
location: Location::default(), location: Location::default(),
id: ItemId::default(), id: ItemId::default(),
@ -33,7 +33,7 @@ fn exst(kind: ExpressionKind) -> Statement {
} }
} }
fn decl(declaration: Declaration) -> Statement { fn decl(declaration: Declaration) -> Statement<StatementKind> {
Statement { Statement {
location: Location::default(), location: Location::default(),
id: ItemId::default(), id: ItemId::default(),
@ -41,7 +41,7 @@ fn decl(declaration: Declaration) -> Statement {
} }
} }
fn fn_decl(sig: Signature, stmts: Block) -> Statement { fn fn_decl(sig: Signature, stmts: Block) -> Statement<StatementKind> {
Statement { Statement {
kind: StatementKind::Declaration(Declaration::FuncDecl(sig, stmts)), kind: StatementKind::Declaration(Declaration::FuncDecl(sig, stmts)),
location: Default::default(), location: Default::default(),
@ -992,14 +992,14 @@ fn impls() {
use Declaration::{FuncDecl, Impl}; use Declaration::{FuncDecl, Impl};
let block = vec![ let block = vec![
FuncDecl( stmt(FuncDecl(
Signature { name: rc("yolo"), operator: false, params: vec![], type_anno: None }, Signature { name: rc("yolo"), operator: false, params: vec![], type_anno: None },
vec![].into(), vec![].into(),
), )),
FuncDecl( stmt(FuncDecl(
Signature { name: rc("swagg"), operator: false, params: vec![], type_anno: None }, Signature { name: rc("swagg"), operator: false, params: vec![], type_anno: None },
vec![].into(), vec![].into(),
), )),
]; ];
assert_ast!( assert_ast!(

View File

@ -65,7 +65,7 @@ impl<'a, 'b> Reducer<'a, 'b> {
ReducedIR { functions: self.functions, entrypoint } ReducedIR { functions: self.functions, entrypoint }
} }
fn top_level_definition(&mut self, statement: &ast::Statement) { fn top_level_definition(&mut self, statement: &ast::Statement<ast::StatementKind>) {
let ast::Statement { id: item_id, kind, .. } = statement; let ast::Statement { id: item_id, kind, .. } = statement;
match kind { match kind {
ast::StatementKind::Expression(_expr) => { ast::StatementKind::Expression(_expr) => {
@ -85,7 +85,10 @@ impl<'a, 'b> Reducer<'a, 'b> {
} }
} }
fn function_internal_statement(&mut self, statement: &ast::Statement) -> Option<Statement> { fn function_internal_statement(
&mut self,
statement: &ast::Statement<ast::StatementKind>,
) -> Option<Statement> {
let ast::Statement { id: item_id, kind, .. } = statement; let ast::Statement { id: item_id, kind, .. } = statement;
match kind { match kind {
ast::StatementKind::Expression(expr) => Some(Statement::Expression(self.expression(expr))), ast::StatementKind::Expression(expr) => Some(Statement::Expression(self.expression(expr))),

View File

@ -35,6 +35,7 @@ pub enum SymbolError {
DuplicateRecord { type_fqsn: Fqsn, location: Location, record: String, member: String }, DuplicateRecord { type_fqsn: Fqsn, location: Location, record: String, member: String },
UnknownAnnotation { name: String }, UnknownAnnotation { name: String },
BadAnnotation { name: String, msg: String }, BadAnnotation { name: String, msg: String },
BadImplBlockEntry,
} }
#[allow(dead_code)] #[allow(dead_code)]

View File

@ -1,5 +1,6 @@
use std::{ use std::{
collections::{hash_map::Entry, HashMap, HashSet}, collections::{hash_map::Entry, HashMap, HashSet},
rc::Rc,
str::FromStr, str::FromStr,
}; };
@ -38,7 +39,7 @@ impl<'a> SymbolTablePopulator<'a> {
fn add_from_scope( fn add_from_scope(
&mut self, &mut self,
statements: &[Statement], statements: &[Statement<StatementKind>],
scope_stack: &mut Vec<ScopeSegment>, scope_stack: &mut Vec<ScopeSegment>,
function_scope: bool, function_scope: bool,
) -> Vec<SymbolError> { ) -> Vec<SymbolError> {
@ -75,11 +76,28 @@ impl<'a> SymbolTablePopulator<'a> {
self.add_type_members(name, body, mutable, location, type_fqsn) self.add_type_members(name, body, mutable, location, type_fqsn)
} }
/* Declaration::Impl { type_name, interface_name, block } => {
Declaration::Impl { type_name, body, .. } => { let mut errors = vec![];
let new_scope = ScopeSegment::Name(Rc::new(format!("<impl-block>{}", type_name)));
scope_stack.push(new_scope);
}, for decl_stmt in block.iter() {
*/ let Statement { id, kind, location } = decl_stmt;
let location = *location;
match kind {
decl @ Declaration::FuncDecl(..) => {
let output =
self.add_single_declaration(id, decl, location, scope_stack, true);
if let Err(e) = output {
errors.push(e);
};
}
_other => errors.push(SymbolError::BadImplBlockEntry),
};
}
scope_stack.pop();
errors
}
_ => vec![], _ => vec![],
}; };
errors.extend(recursive_errs.into_iter()); errors.extend(recursive_errs.into_iter());
@ -98,7 +116,22 @@ impl<'a> SymbolTablePopulator<'a> {
function_scope: bool, function_scope: bool,
) -> Result<(), SymbolError> { ) -> Result<(), SymbolError> {
match kind { match kind {
StatementKind::Declaration(Declaration::FuncSig(signature)) => { StatementKind::Declaration(decl) =>
self.add_single_declaration(id, decl, location, scope_stack, function_scope),
_ => return Ok(()),
}
}
fn add_single_declaration(
&mut self,
id: &ItemId,
decl: &Declaration,
location: Location,
scope_stack: &[ScopeSegment],
function_scope: bool,
) -> Result<(), SymbolError> {
match decl {
Declaration::FuncSig(signature) => {
let fq_function = Fqsn::from_scope_stack(scope_stack, signature.name.clone()); let fq_function = Fqsn::from_scope_stack(scope_stack, signature.name.clone());
self.table self.table
.fq_names .fq_names
@ -109,7 +142,7 @@ impl<'a> SymbolTablePopulator<'a> {
self.add_symbol(id, fq_function, SymbolSpec::Func { method: None }); self.add_symbol(id, fq_function, SymbolSpec::Func { method: None });
} }
StatementKind::Declaration(Declaration::FuncDecl(signature, ..)) => { Declaration::FuncDecl(signature, ..) => {
let fn_name = &signature.name; let fn_name = &signature.name;
let fq_function = Fqsn::from_scope_stack(scope_stack, fn_name.clone()); let fq_function = Fqsn::from_scope_stack(scope_stack, fn_name.clone());
self.table self.table
@ -121,11 +154,13 @@ impl<'a> SymbolTablePopulator<'a> {
self.add_symbol(id, fq_function, SymbolSpec::Func { method: None }); self.add_symbol(id, fq_function, SymbolSpec::Func { method: None });
} }
StatementKind::Declaration(Declaration::TypeDecl { name, .. }) => { Declaration::TypeDecl { name, .. } => {
let fq_type = Fqsn::from_scope_stack(scope_stack, name.name.clone()); let fq_type = Fqsn::from_scope_stack(scope_stack, name.name.clone());
self.table.types.register(fq_type, NameSpec { location, kind: TypeKind::Constructor })?; self.table.types.register(fq_type, NameSpec { location, kind: TypeKind::Constructor })?;
} }
StatementKind::Declaration(Declaration::Binding { name, .. }) => { //TODO handle type aliases
Declaration::TypeAlias { .. } => (),
Declaration::Binding { name, .. } => {
let fq_binding = Fqsn::from_scope_stack(scope_stack, name.clone()); let fq_binding = Fqsn::from_scope_stack(scope_stack, name.clone());
self.table self.table
.fq_names .fq_names
@ -134,11 +169,14 @@ impl<'a> SymbolTablePopulator<'a> {
self.add_symbol(id, fq_binding, SymbolSpec::GlobalBinding); self.add_symbol(id, fq_binding, SymbolSpec::GlobalBinding);
} }
} }
StatementKind::Declaration(Declaration::Module { name, .. }) => { //TODO implement interfaces
Declaration::Interface { .. } => (),
Declaration::Impl { .. } => (),
Declaration::Module { name, .. } => {
let fq_module = Fqsn::from_scope_stack(scope_stack, name.clone()); let fq_module = Fqsn::from_scope_stack(scope_stack, name.clone());
self.table.fq_names.register(fq_module, NameSpec { location, kind: NameKind::Module })?; self.table.fq_names.register(fq_module, NameSpec { location, kind: NameKind::Module })?;
} }
StatementKind::Declaration(Declaration::Annotation { name, arguments, inner }) => { Declaration::Annotation { name, arguments, inner } => {
let inner = inner.as_ref(); let inner = inner.as_ref();
self.add_single_statement( self.add_single_statement(
&inner.id, &inner.id,
@ -149,7 +187,6 @@ impl<'a> SymbolTablePopulator<'a> {
)?; )?;
self.process_annotation(name.as_ref(), arguments.as_slice(), scope_stack, inner)?; self.process_annotation(name.as_ref(), arguments.as_slice(), scope_stack, inner)?;
} }
_ => (),
} }
Ok(()) Ok(())
} }
@ -159,7 +196,7 @@ impl<'a> SymbolTablePopulator<'a> {
name: &str, name: &str,
arguments: &[Expression], arguments: &[Expression],
scope_stack: &[ScopeSegment], scope_stack: &[ScopeSegment],
inner: &Statement, inner: &Statement<StatementKind>,
) -> Result<(), SymbolError> { ) -> Result<(), SymbolError> {
if name == "register_builtin" { if name == "register_builtin" {
if let Statement { if let Statement {

View File

@ -271,9 +271,8 @@ fn duplicate_struct_members() {
); );
} }
/*
#[test] #[test]
fn methods() { fn method_definition_added_to_symbol_table() {
let source = r#" let source = r#"
type Foo = { x: Int, y: Int } type Foo = { x: Int, y: Int }
@ -286,6 +285,28 @@ impl Foo {
"#; "#;
let (symbols, _) = add_symbols(source); let (symbols, _) = add_symbols(source);
symbols.debug(); symbols.debug();
assert!(symbols.fq_names.table.get(&make_fqsn(&["hella"])).is_some()); assert!(symbols.fq_names.table.get(&make_fqsn(&["<impl-block>Foo", "hella"])).is_some());
}
#[test]
fn duplicate_method_definitions_detected() {
let source = r#"
type Foo = { x: Int, y: Int }
impl Foo {
fn hella() {
self.x + 50
}
fn hella() {
self.x + 40
}
}
"#;
let (_symbols, output) = add_symbols(source);
let errs = output.unwrap_err();
assert_matches!(&errs[..], [
SymbolError::DuplicateName { prev_name: pn1, ..},
] if pn1 == &Fqsn::from_strs(&["<impl-block>Foo", "hella"]));
} }
*/

View File

@ -4,7 +4,7 @@ use crate::{
reduced_ir::{Callable, Expression, FunctionDefinition, Literal, ReducedIR}, reduced_ir::{Callable, Expression, FunctionDefinition, Literal, ReducedIR},
symbol_table::DefId, symbol_table::DefId,
type_inference::{TypeContext, TypeId}, type_inference::{TypeContext, TypeId},
util::ScopeStack, util::{delim_wrapped, ScopeStack},
}; };
mod evaluator; mod evaluator;
@ -61,19 +61,6 @@ impl RuntimeError {
} }
} }
fn delim_wrapped(lhs: char, rhs: char, terms: impl Iterator<Item = String>) -> String {
let mut buf = String::new();
write!(buf, "{}", lhs).unwrap();
for term in terms.map(Some).intersperse(None) {
match term {
Some(e) => write!(buf, "{}", e).unwrap(),
None => write!(buf, ", ").unwrap(),
};
}
write!(buf, "{}", rhs).unwrap();
buf
}
/// Anything that can be stored in memory; that is, a function definition, or a fully-evaluated /// Anything that can be stored in memory; that is, a function definition, or a fully-evaluated
/// program value. /// program value.
#[derive(Debug)] #[derive(Debug)]

View File

@ -1,4 +1,18 @@
use std::{cmp::Eq, collections::HashMap, hash::Hash}; use std::{cmp::Eq, collections::HashMap, fmt::Write, hash::Hash};
/// Utility function for printing a comma-delimited list of things
pub(crate) fn delim_wrapped(lhs: char, rhs: char, terms: impl Iterator<Item = String>) -> String {
let mut buf = String::new();
write!(buf, "{}", lhs).unwrap();
for term in terms.map(Some).intersperse(None) {
match term {
Some(e) => write!(buf, "{}", e).unwrap(),
None => write!(buf, ", ").unwrap(),
};
}
write!(buf, "{}", rhs).unwrap();
buf
}
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct ScopeStack<'a, T: 'a, V: 'a, N = String> pub struct ScopeStack<'a, T: 'a, V: 'a, N = String>