Add rudimentary type-use parsing and type-checking parameters.
This commit is contained in:
parent
2d601d6115
commit
0a0065a2c1
@ -13,3 +13,4 @@ pub mod module_level_declaration;
|
||||
pub mod parameter;
|
||||
pub mod statement;
|
||||
pub mod string_literal;
|
||||
pub mod type_use;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use crate::ast::type_use::TypeUse;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::ParameterSymbol;
|
||||
@ -9,13 +10,19 @@ use std::rc::Rc;
|
||||
pub struct Parameter {
|
||||
declared_name: String,
|
||||
declared_name_source_range: SourceRange,
|
||||
type_use: TypeUse,
|
||||
}
|
||||
|
||||
impl Parameter {
|
||||
pub fn new(declared_name: &str, declared_name_source_range: SourceRange) -> Self {
|
||||
pub fn new(
|
||||
declared_name: &str,
|
||||
declared_name_source_range: SourceRange,
|
||||
type_use: TypeUse,
|
||||
) -> Self {
|
||||
Self {
|
||||
declared_name: declared_name.into(),
|
||||
declared_name_source_range,
|
||||
type_use,
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +32,7 @@ impl Parameter {
|
||||
) -> Result<Rc<RefCell<ParameterSymbol>>, Vec<Diagnostic>> {
|
||||
let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new(
|
||||
&self.declared_name,
|
||||
TypeInfo::Any, // todo
|
||||
TypeInfo::from_declared_name(self.type_use.declared_name()),
|
||||
));
|
||||
match insert_result {
|
||||
Ok(parameter_symbol) => Ok(parameter_symbol),
|
||||
|
||||
19
dmc-lib/src/ast/type_use.rs
Normal file
19
dmc-lib/src/ast/type_use.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use crate::source_range::SourceRange;
|
||||
|
||||
pub struct TypeUse {
|
||||
declared_name: String,
|
||||
declared_name_source_range: SourceRange,
|
||||
}
|
||||
|
||||
impl TypeUse {
|
||||
pub fn new(declared_name: &str, declared_name_source_range: SourceRange) -> Self {
|
||||
Self {
|
||||
declared_name: declared_name.into(),
|
||||
declared_name_source_range,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn declared_name(&self) -> &str {
|
||||
&self.declared_name
|
||||
}
|
||||
}
|
||||
@ -46,6 +46,8 @@ impl<'a> Lexer<'a> {
|
||||
Token::new(self.position, self.position + 1, TokenKind::Equals)
|
||||
} else if chunk.starts_with(",") {
|
||||
Token::new(self.position, self.position + 1, TokenKind::Comma)
|
||||
} else if chunk.starts_with(":") {
|
||||
Token::new(self.position, self.position + 1, TokenKind::Colon)
|
||||
} else {
|
||||
// more than one char token
|
||||
if chunk.starts_with(|c: char| c.is_ascii_digit()) {
|
||||
|
||||
@ -11,6 +11,7 @@ use crate::ast::module_level_declaration::ModuleLevelDeclaration;
|
||||
use crate::ast::parameter::Parameter;
|
||||
use crate::ast::statement::Statement;
|
||||
use crate::ast::string_literal::StringLiteral;
|
||||
use crate::ast::type_use::TypeUse;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::lexer::Lexer;
|
||||
use crate::source_range::SourceRange;
|
||||
@ -309,14 +310,29 @@ impl<'a> Parser<'a> {
|
||||
self.advance();
|
||||
}
|
||||
}
|
||||
Ok(parameters)
|
||||
if diagnostics.is_empty() {
|
||||
Ok(parameters)
|
||||
} else {
|
||||
Err(diagnostics)
|
||||
}
|
||||
}
|
||||
|
||||
fn parameter(&mut self) -> Result<Parameter, Vec<Diagnostic>> {
|
||||
let identifier_token = self.expect_advance(TokenKind::Identifier)?;
|
||||
self.expect_advance(TokenKind::Colon)?;
|
||||
let type_use = self.type_use()?;
|
||||
Ok(Parameter::new(
|
||||
self.token_text(&identifier_token),
|
||||
SourceRange::new(identifier_token.start(), identifier_token.end()),
|
||||
type_use,
|
||||
))
|
||||
}
|
||||
|
||||
fn type_use(&mut self) -> Result<TypeUse, Vec<Diagnostic>> {
|
||||
let identifier_token = self.expect_advance(TokenKind::Identifier)?;
|
||||
Ok(TypeUse::new(
|
||||
self.token_text(&identifier_token),
|
||||
SourceRange::new(identifier_token.start(), identifier_token.end()),
|
||||
))
|
||||
}
|
||||
|
||||
@ -464,7 +480,7 @@ mod smoke_tests {
|
||||
|
||||
#[test]
|
||||
fn extern_fn_with_param() {
|
||||
smoke_test("extern fn println(message)")
|
||||
smoke_test("extern fn println(message: Any)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -37,4 +37,5 @@ pub enum TokenKind {
|
||||
String,
|
||||
Extern,
|
||||
Comma,
|
||||
Colon,
|
||||
}
|
||||
|
||||
@ -29,6 +29,16 @@ impl Display for TypeInfo {
|
||||
}
|
||||
|
||||
impl TypeInfo {
|
||||
// This is very naive but works for now
|
||||
pub fn from_declared_name(declared_name: &str) -> Self {
|
||||
match declared_name {
|
||||
"Any" => TypeInfo::Any,
|
||||
"Int" => TypeInfo::Integer,
|
||||
"String" => TypeInfo::String,
|
||||
_ => panic!("Unknown type: {}", declared_name),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_assignable_from(&self, other: &TypeInfo) -> bool {
|
||||
match self {
|
||||
TypeInfo::Any => true,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
extern fn println(message)
|
||||
extern fn println(message: Any)
|
||||
|
||||
fn main()
|
||||
let x = "Hello, World!"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user