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::*; 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)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CallExpression { pub struct CallExpression {
/// An expression evaluating to a callable function, /// An expression evaluating to a callable function,
@ -24,13 +24,23 @@ pub struct CallExpression {
pub function: Box<Expression>, // todo: make this identifier? pub function: Box<Expression>, // todo: make this identifier?
/// Expressions for the arguments passed to the functions parameters. /// Expressions for the arguments passed to the functions parameters.
pub arguments: Vec<Expression>, 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)`. /// Span of the entire call `function(arguments)`.
pub span: Span, pub span: Span,
} }
impl fmt::Display for CallExpression { impl fmt::Display for CallExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 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() { for (i, param) in self.arguments.iter().enumerate() {
write!(f, "{}", param)?; write!(f, "{}", param)?;
if i < self.arguments.len() - 1 { if i < self.arguments.len() - 1 {

View File

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

View File

@ -364,6 +364,21 @@ impl ParserContext<'_> {
index, index,
span, 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 { } else {
// Parse identifier name. // Parse identifier name.
let name = self.expect_identifier()?; let name = self.expect_identifier()?;
@ -389,6 +404,7 @@ impl ParserContext<'_> {
expr = Expression::Call(CallExpression { expr = Expression::Call(CallExpression {
span: expr.span() + span, span: expr.span() + span,
function: Box::new(expr), function: Box::new(expr),
external: None,
arguments, arguments,
}); });
} }

View File

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

View File

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

View File

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

View File

@ -276,7 +276,10 @@ impl<'a> CodeGenerator<'a> {
} }
fn visit_call(&mut self, input: &'a CallExpression) -> (String, String) { 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(); let mut instructions = String::new();
for argument in input.arguments.iter() { for argument in input.arguments.iter() {

View File

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

View File

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

View File