Skip to content

Commit

Permalink
Finished initial support for parsing for generics / compile-time argu…
Browse files Browse the repository at this point in the history
…ments
  • Loading branch information
IsaacShelton committed Sep 11, 2024
1 parent 2e0959a commit e7febd0
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 43 deletions.
3 changes: 2 additions & 1 deletion src/ast/expr/call.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use super::Expr;
use crate::ast::Type;
use crate::ast::{CompileTimeArgument, Type};

#[derive(Clone, Debug)]
pub struct Call {
pub function_name: String,
pub arguments: Vec<Expr>,
pub expected_to_return: Option<Type>,
pub generics: Vec<CompileTimeArgument>,
}
1 change: 1 addition & 0 deletions src/interpreter_env/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
function_name: "main".into(),
arguments: vec![],
expected_to_return: Some(void.clone()),
generics: vec![],
}))
.at(Source::internal());

Expand Down
8 changes: 4 additions & 4 deletions src/parser/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ pub enum ParseErrorKind {
DefineHasMultipleDefinitions {
name: String,
},
ExpectedEnumName,
ExpectedEnumMemberName,
Lexical {
message: String,
Expand All @@ -84,6 +83,7 @@ pub enum ParseErrorKind {
name: String,
word_for_nth: String,
},
GenericsNotSupportedHere,
Other {
message: String,
},
Expand Down Expand Up @@ -180,9 +180,6 @@ impl Display for ParseErrorKind {
ParseErrorKind::DefineHasMultipleDefinitions { name } => {
write!(f, "Define '{}' has multiple definitions", name)?;
}
ParseErrorKind::ExpectedEnumName => {
write!(f, "Expected enum name")?;
}
ParseErrorKind::ExpectedEnumMemberName => {
write!(f, "Expected enum member name")?;
}
Expand All @@ -207,6 +204,9 @@ impl Display for ParseErrorKind {
word_for_nth, name
)?;
}
ParseErrorKind::GenericsNotSupportedHere => {
write!(f, "Generics not supported here")?;
}
ParseErrorKind::Other { message } | ParseErrorKind::Lexical { message } => {
write!(f, "{}", message)?;
}
Expand Down
5 changes: 3 additions & 2 deletions src/parser/parse_expr/post/member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
let source = self.parse_token(TokenKind::Member, Some("for member expression"))?;
let member_name = self.parse_identifier(Some("for member name"))?;

if self.input.peek_is(TokenKind::OpenParen) {
self.parse_call_with(member_name, vec![subject], source)
if self.input.peek_is(TokenKind::OpenParen) || self.input.peek_is(TokenKind::OpenAngle) {
let generics = self.parse_generics()?;
self.parse_call_with(member_name, generics, vec![subject], source)
} else {
Ok(ExprKind::Member(Box::new(subject), member_name).at(source))
}
Expand Down
16 changes: 10 additions & 6 deletions src/parser/parse_expr/primary/call.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
use super::Parser;
use crate::{
ast::{Call, Expr, ExprKind},
ast::{Call, CompileTimeArgument, Expr, ExprKind},
inflow::Inflow,
parser::error::ParseError,
source_files::Source,
token::{Token, TokenKind},
};

impl<'a, I: Inflow<Token>> Parser<'a, I> {
pub fn parse_call(&mut self) -> Result<Expr, ParseError> {
pub fn parse_call(
&mut self,
function_name: String,
generics: Vec<CompileTimeArgument>,
source: Source,
) -> Result<Expr, ParseError> {
// function_name(arg1, arg2, arg3)
// ^

let (function_name, source) =
self.parse_identifier_keep_location(Some("for function call"))?;

self.parse_call_with(function_name, vec![], source)
self.parse_call_with(function_name, generics, vec![], source)
}

pub fn parse_call_with(
&mut self,
function_name: String,
generics: Vec<CompileTimeArgument>,
prefix_args: Vec<Expr>,
source: Source,
) -> Result<Expr, ParseError> {
Expand All @@ -45,6 +48,7 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
function_name,
arguments: args,
expected_to_return: None,
generics,
}))
.at(source))
}
Expand Down
12 changes: 7 additions & 5 deletions src/parser/parse_expr/primary/declare_assign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ use crate::{
ast::{DeclareAssign, Expr, ExprKind},
inflow::Inflow,
parser::error::ParseError,
source_files::Source,
token::{Token, TokenKind},
};

impl<'a, I: Inflow<Token>> Parser<'a, I> {
pub fn parse_declare_assign(&mut self) -> Result<Expr, ParseError> {
pub fn parse_declare_assign(
&mut self,
variable_name: String,
source: Source,
) -> Result<Expr, ParseError> {
// variable_name := value
// ^

let (variable_name, source) =
self.parse_identifier_keep_location(Some("for function call"))?;
// ^

self.parse_token(
TokenKind::DeclareAssign,
Expand Down
15 changes: 7 additions & 8 deletions src/parser/parse_expr/primary/enum_member_literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,26 @@ use crate::{
ast::{EnumMemberLiteral, Expr, ExprKind},
inflow::Inflow,
parser::error::{ParseError, ParseErrorKind},
source_files::Source,
token::{Token, TokenKind},
};

impl<'a, I: Inflow<Token>> Parser<'a, I> {
pub fn parse_enum_member_literal(&mut self) -> Result<Expr, ParseError> {
pub fn parse_enum_member_literal(
&mut self,
enum_name: String,
source: Source,
) -> Result<Expr, ParseError> {
// EnumName::EnumVariant
// ^

let source = self.source_here();
let enum_name = self
.input
.eat_identifier()
.ok_or_else(|| ParseErrorKind::ExpectedEnumName.at(source))?;

self.parse_token(TokenKind::Namespace, Some("for enum member literal"))?;

let variant_source = self.source_here();
let variant_name = self
.input
.eat_identifier()
.ok_or_else(|| ParseErrorKind::ExpectedEnumName.at(variant_source))?;
.ok_or_else(|| ParseErrorKind::ExpectedEnumMemberName.at(variant_source))?;

Ok(ExprKind::EnumMemberLiteral(Box::new(EnumMemberLiteral {
enum_name,
Expand Down
42 changes: 25 additions & 17 deletions src/parser/parse_expr/primary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,32 +70,31 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
// TODO: CLEANUP: This should be cleaned up once we have proper
// namespaces and generic parsing that applies to all cases

match self.input.peek_nth(1).kind {
TokenKind::Namespace => self.parse_enum_member_literal(),
TokenKind::OpenAngle => {
let name = self.input.eat_identifier().unwrap();
let generics = self.parse_generics()?;
let name = self.input.eat_identifier().unwrap();
let generics = self.parse_generics()?;

match self.input.peek().kind {
TokenKind::Namespace => {
if !generics.is_empty() {
todo!("generics in expressions not implemented yet");
return Err(ParseErrorKind::GenericsNotSupportedHere.at(source));
}

let ast_type = self.parse_type_from_parts(name, vec![], source)?;
self.parse_structure_literal_with(ast_type)
self.parse_enum_member_literal(name, source)
}
TokenKind::OpenCurly => {
let peek = &self.input.peek_nth(2).kind;
let ast_type = self.parse_type_from_parts(name, generics, source)?;
let peek = &self.input.peek_nth(1).kind;

if peek.is_extend() || peek.is_colon() {
self.parse_structure_literal()
self.parse_structure_literal_with(ast_type)
} else {
let next_three =
array_last::<3, 5, _>(self.input.peek_n()).map(|token| &token.kind);

match &next_three[..] {
[TokenKind::Identifier(_), TokenKind::Colon, ..]
| [TokenKind::Newline, TokenKind::Identifier(_), TokenKind::Colon, ..] => {
self.parse_structure_literal()
self.parse_structure_literal_with(ast_type)
}
_ => Ok(Expr::new(
ExprKind::Variable(
Expand All @@ -106,12 +105,21 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
}
}
}
TokenKind::OpenParen => self.parse_call(),
TokenKind::DeclareAssign => self.parse_declare_assign(),
_ => Ok(Expr::new(
ExprKind::Variable(self.input.advance().kind.unwrap_identifier()),
source,
)),
TokenKind::OpenParen => self.parse_call(name, generics, source),
TokenKind::DeclareAssign => {
if !generics.is_empty() {
return Err(ParseErrorKind::GenericsNotSupportedHere.at(source));
}

self.parse_declare_assign(name, source)
}
_ => {
if !generics.is_empty() {
return Err(ParseErrorKind::GenericsNotSupportedHere.at(source));
}

Ok(Expr::new(ExprKind::Variable(name), source))
}
}
}
TokenKind::Not | TokenKind::BitComplement | TokenKind::Subtract => {
Expand Down
7 changes: 7 additions & 0 deletions src/resolve/expr/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ pub fn resolve_call_expr(
call: &ast::Call,
source: Source,
) -> Result<TypedExpr, ResolveError> {
if !call.generics.is_empty() {
return Err(ResolveErrorKind::Other {
message: "Resolution of calls with generics is not implemented yet".into(),
}
.at(source));
}

let function_ref = ctx
.function_search_ctx
.find_function_or_error(&call.function_name, source)?;
Expand Down

0 comments on commit e7febd0

Please sign in to comment.