push code to parse external calls

This commit is contained in:
collin 2022-09-20 13:58:52 -07:00
parent 93307b1446
commit 0a86a05d20
10 changed files with 45 additions and 10 deletions

View File

@ -16,7 +16,7 @@
use super::*;
/// A function call expression, e.g., `foo(args)` or `Foo::bar(args)`.
/// A function call expression, e.g.`foo(args)` or `Foo::bar(args)`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CallExpression {
/// An expression evaluating to a callable function,
@ -24,13 +24,23 @@ pub struct CallExpression {
pub function: Box<Expression>, // todo: make this identifier?
/// Expressions for the arguments passed to the functions parameters.
pub arguments: Vec<Expression>,
/// The name of the external program call, e.g.`bar` in `bar.leo`.
pub external: Option<Box<Expression>>,
/// Span of the entire call `function(arguments)`.
pub span: Span,
}
impl fmt::Display for CallExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}(", self.function)?;
match &self.external {
Some(external) => {
write!(f, "{}.leo/{}(", external, self.function)?;
}
None => {
write!(f, "{}(", self.function)?;
}
}
for (i, param) in self.arguments.iter().enumerate() {
write!(f, "{}", param)?;
if i < self.arguments.len() - 1 {

View File

@ -91,6 +91,7 @@ pub trait ExpressionReconstructor {
.into_iter()
.map(|arg| self.reconstruct_expression(arg).0)
.collect(),
external: input.external,
span: input.span,
}),
Default::default(),

View File

@ -364,6 +364,21 @@ impl ParserContext<'_> {
index,
span,
}))
} else if self.eat(&Token::Leo) {
// Eat an external function call.
self.eat(&Token::Div); // todo: Make `/` a more general token.
// Parse function name.
let name = self.expect_identifier()?;
// Parse the function call.
let (arguments, _, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
expr = Expression::Call(CallExpression {
span: expr.span() + span,
function: Box::new(Expression::Identifier(name)),
external: Some(Box::new(expr)),
arguments,
});
} else {
// Parse identifier name.
let name = self.expect_identifier()?;
@ -389,6 +404,7 @@ impl ParserContext<'_> {
expr = Expression::Call(CallExpression {
span: expr.span() + span,
function: Box::new(expr),
external: None,
arguments,
});
}

View File

@ -95,12 +95,11 @@ impl ParserContext<'_> {
// Parse `.leo`.
self.expect(&Token::Dot)?;
let leo_file_extension = self.expect_identifier()?;
// Throw error for non-leo files.
if leo_file_extension.name.ne(&sym::leo) {
return Err(ParserError::leo_imports_only(leo_file_extension, self.token.span).into());
if !self.eat(&Token::Leo) {
// Throw error for non-leo files.
return Err(ParserError::leo_imports_only(self.token.span).into());
}
let _end = self.expect(&Token::Semicolon)?;
// Tokenize and parse import file.

View File

@ -417,6 +417,7 @@ impl Token {
"increment" => Token::Increment,
"import" => Token::Import,
"let" => Token::Let,
"leo" => Token::Leo,
"mapping" => Token::Mapping,
"public" => Token::Public,
"record" => Token::Record,

View File

@ -130,6 +130,8 @@ pub enum Token {
Return,
SelfLower,
Static,
// For imports.
Leo,
// Meta Tokens
Eof,
@ -213,6 +215,7 @@ impl Token {
Token::Increment => sym::increment,
Token::Import => sym::import,
Token::Let => sym::Let,
Token::Leo => sym::leo,
Token::Mapping => sym::mapping,
Token::Public => sym::Public,
Token::Record => sym::record,
@ -335,6 +338,7 @@ impl fmt::Display for Token {
Public => write!(f, "public"),
Return => write!(f, "return"),
Static => write!(f, "static"),
Leo => write!(f, "leo"),
Eof => write!(f, "<eof>"),
}
}

View File

@ -276,7 +276,10 @@ impl<'a> CodeGenerator<'a> {
}
fn visit_call(&mut self, input: &'a CallExpression) -> (String, String) {
let mut call_instruction = format!(" call {} ", input.function);
let mut call_instruction = match &input.external {
Some(external) => format!(" call {}.aleo/{} ", external, input.function),
None => format!(" call {} ", input.function),
};
let mut instructions = String::new();
for argument in input.arguments.iter() {

View File

@ -133,6 +133,7 @@ impl ExpressionConsumer for StaticSingleAssigner {
function: input.function,
// Consume the arguments.
arguments,
external: input.external,
span: input.span,
}));
statements.push(statement);

View File

@ -249,8 +249,8 @@ create_messages!(
@formatted
leo_imports_only {
args: (name: impl Display),
msg: format!("Invalid import call to non-leo file `{name}`."),
args: (),
msg: "Invalid import call to non-leo file.",
help: Some("Only imports of Leo `.leo` files are currently supported.".to_string()),
}

View File