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 parameter;
|
||||||
pub mod statement;
|
pub mod statement;
|
||||||
pub mod string_literal;
|
pub mod string_literal;
|
||||||
|
pub mod type_use;
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use crate::ast::type_use::TypeUse;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::ParameterSymbol;
|
use crate::symbol::ParameterSymbol;
|
||||||
@ -9,13 +10,19 @@ use std::rc::Rc;
|
|||||||
pub struct Parameter {
|
pub struct Parameter {
|
||||||
declared_name: String,
|
declared_name: String,
|
||||||
declared_name_source_range: SourceRange,
|
declared_name_source_range: SourceRange,
|
||||||
|
type_use: TypeUse,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parameter {
|
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 {
|
Self {
|
||||||
declared_name: declared_name.into(),
|
declared_name: declared_name.into(),
|
||||||
declared_name_source_range,
|
declared_name_source_range,
|
||||||
|
type_use,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +32,7 @@ impl Parameter {
|
|||||||
) -> Result<Rc<RefCell<ParameterSymbol>>, Vec<Diagnostic>> {
|
) -> Result<Rc<RefCell<ParameterSymbol>>, Vec<Diagnostic>> {
|
||||||
let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new(
|
let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new(
|
||||||
&self.declared_name,
|
&self.declared_name,
|
||||||
TypeInfo::Any, // todo
|
TypeInfo::from_declared_name(self.type_use.declared_name()),
|
||||||
));
|
));
|
||||||
match insert_result {
|
match insert_result {
|
||||||
Ok(parameter_symbol) => Ok(parameter_symbol),
|
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)
|
Token::new(self.position, self.position + 1, TokenKind::Equals)
|
||||||
} else if chunk.starts_with(",") {
|
} else if chunk.starts_with(",") {
|
||||||
Token::new(self.position, self.position + 1, TokenKind::Comma)
|
Token::new(self.position, self.position + 1, TokenKind::Comma)
|
||||||
|
} else if chunk.starts_with(":") {
|
||||||
|
Token::new(self.position, self.position + 1, TokenKind::Colon)
|
||||||
} else {
|
} else {
|
||||||
// more than one char token
|
// more than one char token
|
||||||
if chunk.starts_with(|c: char| c.is_ascii_digit()) {
|
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::parameter::Parameter;
|
||||||
use crate::ast::statement::Statement;
|
use crate::ast::statement::Statement;
|
||||||
use crate::ast::string_literal::StringLiteral;
|
use crate::ast::string_literal::StringLiteral;
|
||||||
|
use crate::ast::type_use::TypeUse;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::lexer::Lexer;
|
use crate::lexer::Lexer;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
@ -309,14 +310,29 @@ impl<'a> Parser<'a> {
|
|||||||
self.advance();
|
self.advance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(parameters)
|
if diagnostics.is_empty() {
|
||||||
|
Ok(parameters)
|
||||||
|
} else {
|
||||||
|
Err(diagnostics)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parameter(&mut self) -> Result<Parameter, Vec<Diagnostic>> {
|
fn parameter(&mut self) -> Result<Parameter, Vec<Diagnostic>> {
|
||||||
let identifier_token = self.expect_advance(TokenKind::Identifier)?;
|
let identifier_token = self.expect_advance(TokenKind::Identifier)?;
|
||||||
|
self.expect_advance(TokenKind::Colon)?;
|
||||||
|
let type_use = self.type_use()?;
|
||||||
Ok(Parameter::new(
|
Ok(Parameter::new(
|
||||||
self.token_text(&identifier_token),
|
self.token_text(&identifier_token),
|
||||||
SourceRange::new(identifier_token.start(), identifier_token.end()),
|
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]
|
#[test]
|
||||||
fn extern_fn_with_param() {
|
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,
|
String,
|
||||||
Extern,
|
Extern,
|
||||||
Comma,
|
Comma,
|
||||||
|
Colon,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,16 @@ impl Display for TypeInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn is_assignable_from(&self, other: &TypeInfo) -> bool {
|
||||||
match self {
|
match self {
|
||||||
TypeInfo::Any => true,
|
TypeInfo::Any => true,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
extern fn println(message)
|
extern fn println(message: Any)
|
||||||
|
|
||||||
fn main()
|
fn main()
|
||||||
let x = "Hello, World!"
|
let x = "Hello, World!"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user