Create and implement AST structs/enums and Unparse traits.

This commit is contained in:
Jesse Brault 2025-05-11 09:28:00 -05:00
parent 1a365481ab
commit e8aff842ed
5 changed files with 2136 additions and 306 deletions

View File

@ -0,0 +1,16 @@
class Counter {
fld count: Int
mut getAndIncrement() -> Int {
let result = count
count++
result
}
}
@Synthetic
class MyClosure(delegate: Counter) : MutClosure(Int, Int) -> Int |delegate| {
mut fn call(x: Int, y: Int) -> Int {
x + y + delegate.getAndIncrement()
}
}

View File

@ -0,0 +1,14 @@
pub type Iterator<T> |backing: &Any| = mut fn () -> Option<&T ref backing>
pub int Iterable<T> {
ref fn iterator() -> Iterator<T>(&self)
}
fn main() {
let nums: List<Int> = [1, 2, 3]
let iterator: Iterator<Int> |backing = nums| = nums.iterator()
let first: &Int ref nums = iterator().unwrap()
let second: &Int ref nums = iterator().unwrap()
let third: &Int ref nums = iterator().unwrap()
println "${*first}, ${*second}, ${*third}"
}

View File

@ -1,256 +1,507 @@
use crate::vm::source_code_location::SourceCodeLocation;
use pest::Parser;
pub mod build;
pub mod unparse;
// Operators
#[derive(Debug)]
pub struct CompilationUnit {
namespace: Option<Fqn>,
declarations: Vec<Declaration>,
pub enum Operator {
Binary(BinaryOperator),
Unary(UnaryOperator),
}
impl CompilationUnit {
pub fn namespace(&self) -> &Option<Fqn> {
&self.namespace
}
#[derive(Debug)]
pub enum BinaryOperator {
Or,
And,
EqualTo,
NotEqualTo,
Greater,
Less,
GreaterEqual,
LessEqual,
Add,
Subtract,
Multiply,
Divide,
Modulo,
LeftShift,
RightShift,
}
pub fn declarations(&self) -> &Vec<Declaration> {
&self.declarations
}
#[derive(Debug)]
pub enum UnaryOperator {
Not,
Negative,
PlusPlus,
MinusMinus,
CallOp,
Spread,
}
// Names
#[derive(Debug, Clone)]
pub struct Identifier {
pub name: String,
}
#[derive(Debug)]
pub struct Fqn {
identifiers: Vec<Identifier>,
pub identifiers: Vec<Identifier>,
}
impl Fqn {
pub fn new(identifiers: Vec<Identifier>) -> Self {
Fqn { identifiers }
}
pub fn identifiers(&self) -> &Vec<Identifier> {
&self.identifiers
}
pub fn push_identifier(&mut self, identifier: Identifier) {
self.identifiers.push(identifier);
}
pub fn pop_identifier(&mut self) {
self.identifiers.pop();
}
}
// Generic parameters
#[derive(Debug)]
pub enum Declaration {
Interface {
identifier: Identifier,
is_extern: bool,
is_public: bool,
type_declaration: TypeDeclaration,
},
Implementation {
identifier: Identifier,
is_extern: bool,
is_public: bool,
type_declaration: TypeDeclaration,
impl_ctor: Option<ClassConstructor>,
},
Module {
identifier: Identifier,
is_extern: bool,
is_public: bool,
declarations: Vec<Declaration>,
},
Function(FunctionDeclaration),
Prop(Prop),
Field(Field),
}
pub struct GenericParameters(pub Vec<GenericParameter>);
#[derive(Debug)]
pub struct FunctionDeclaration {
source_code_location: SourceCodeLocation,
identifier: Identifier,
is_extern: bool,
is_public: bool,
parameters: Vec<Parameter>,
declared_type: Option<TypeUse>,
block_statement: BlockStatement,
}
impl FunctionDeclaration {
pub fn source_code_location(&self) -> &SourceCodeLocation {
&self.source_code_location
}
pub fn identifier(&self) -> &Identifier {
&self.identifier
}
pub fn block_statement(&self) -> &BlockStatement {
&self.block_statement
}
}
#[derive(Debug)]
pub struct TypeDeclaration {
generics: Vec<GenericParameter>,
extends: Vec<TypeUse>,
declarations: Vec<Declaration>,
}
impl TypeDeclaration {
pub fn new(
generics: Vec<GenericParameter>,
extends: Vec<TypeUse>,
declarations: Vec<Declaration>,
) -> TypeDeclaration {
TypeDeclaration {
generics,
extends,
declarations,
}
}
}
#[derive(Debug, Clone)]
pub struct Identifier {
name: String,
}
impl Identifier {
pub fn name(&self) -> &str {
&self.name
impl GenericParameters {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct GenericParameter {
identifier: Identifier,
bound: Option<GenericBound>,
}
// Generic arguments
#[derive(Debug)]
pub enum GenericBound {
Extends { fqn: Fqn },
Super { fqn: Fqn },
pub struct GenericArguments(pub Vec<GenericArgument>);
impl GenericArguments {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct GenericArgument {
fqn: Fqn,
pub fqn: Fqn,
}
// Type-use and components
#[derive(Debug)]
pub struct TypeUse {
fqn: Fqn,
generics: Vec<GenericArgument>,
pub fqn: Fqn,
pub arguments: Option<TypeArguments>,
}
#[derive(Debug)]
pub struct ClassConstructor {
args: Vec<ClassMember>,
pub enum TypeArguments {
Generics(GenericArguments),
Tuple(TupleArguments),
Function(FunctionTypeArguments),
}
impl ClassConstructor {
pub fn new(args: Vec<ClassMember>) -> Self {
ClassConstructor { args }
#[derive(Debug)]
pub struct TupleArguments(pub Vec<Fqn>);
impl TupleArguments {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct ClassMember {
is_field: bool,
identifier: Identifier,
type_use: Option<TypeUse>
pub struct FunctionTypeArguments {
pub parameters: Parameters,
pub return_type: Box<TypeUse>,
}
impl ClassMember {
pub fn new(is_field: bool, identifier: Identifier, type_use: Option<TypeUse>) -> Self {
ClassMember {
is_field,
identifier,
type_use
}
// Function components
#[derive(Debug)]
pub struct Parameters(pub Vec<Parameter>);
impl Parameters {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct ImplCtorArg {
is_field: bool,
pub struct Parameter {
identifier: Identifier,
r#type: Option<TypeUse>,
type_use: TypeUse,
}
#[derive(Debug)]
pub struct Prop {
identifier: Identifier,
r#type: TypeUse,
pub struct ReturnType {
pub type_use: Box<TypeUse>,
pub references: References,
}
#[derive(Debug)]
pub struct Field {
identifier: Identifier,
r#type: TypeUse,
}
pub struct References(pub Vec<Reference>);
#[derive(Debug)]
pub struct BlockStatement {
statements: Vec<Statement>,
}
impl BlockStatement {
pub fn statements(&self) -> &Vec<Statement> {
&self.statements
impl References {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct Reference {
pub identifier: Identifier,
}
// Inputs
#[derive(Debug)]
pub enum DelegateOrIdentifier {
Delegate,
Identifier(Identifier),
}
#[derive(Debug)]
pub struct InputParameters(pub Vec<DelegateOrIdentifier>);
impl InputParameters {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct InputArguments(pub Vec<InputArgument>);
impl InputArguments {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct InputArgument {
pub lhs: DelegateOrIdentifier,
pub rhs: Identifier
}
// Where guards
#[derive(Debug)]
pub struct WhereGuards(pub Vec<WhereGuard>);
impl WhereGuards {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct WhereGuard {
pub identifier: Identifier,
pub implements: ImplementsList
}
// Implements
#[derive(Debug)]
pub struct ImplementsList(pub Vec<TypeUse>);
impl ImplementsList {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
// Top-level construct
#[derive(Debug)]
pub struct CompilationUnit {
pub namespace: Option<Fqn>,
pub declarations: Vec<ModuleLevelDeclaration>,
}
// Declarations allowed in each level
#[derive(Debug)]
pub enum ModuleLevelDeclaration {
Type(TypeDeclaration),
Module(ModuleDeclaration),
Interface(InterfaceDeclaration),
Class(ClassDeclaration),
Function(FunctionDeclaration),
PlatformFunction(PlatformFunctionDeclaration),
}
#[derive(Debug)]
pub enum InterfaceLevelDeclaration {
Type(TypeDeclaration),
Module(ModuleDeclaration),
Interface(InterfaceDeclaration),
Class(ClassDeclaration),
Function(InterfaceFunctionDeclaration),
OperatorFunction(InterfaceOperatorFunctionDeclaration),
}
#[derive(Debug)]
pub enum ClassLevelDeclaration {
Type(TypeDeclaration),
Module(ModuleDeclaration),
Interface(InterfaceDeclaration),
Class(ClassDeclaration),
Function(FunctionDeclaration),
OperatorFunction(OperatorFunctionDeclaration),
PlatformFunction(PlatformFunctionDeclaration),
Field(FieldDeclaration),
}
// Declarations
#[derive(Debug)]
pub struct TypeDeclaration {
pub is_public: bool,
pub identifier: Identifier,
pub parameters: Option<TypeParameters>,
pub where_guards: WhereGuards,
pub rhs: TypeUse,
}
#[derive(Debug)]
pub struct ModuleDeclaration {
pub is_public: bool,
pub identifier: Identifier,
pub declarations: Vec<ModuleLevelDeclaration>,
}
#[derive(Debug)]
pub struct InterfaceDeclaration {
pub is_public: bool,
pub identifier: Identifier,
pub generics: GenericParameters,
pub inputs: InputParameters,
pub implements: ImplementsList,
pub where_guards: WhereGuards,
pub declarations: Vec<InterfaceLevelDeclaration>,
}
#[derive(Debug)]
pub struct ClassDeclaration {
pub is_public: bool,
pub identifier: Identifier,
pub generics: GenericParameters,
pub class_constructor: Option<ClassConstructor>,
pub inputs: InputArguments,
pub implements: ImplementsList,
pub where_guards: WhereGuards,
pub declarations: Vec<ClassLevelDeclaration>,
}
// Function declarations and components
#[derive(Debug)]
pub enum FunctionModifier {
Static,
Cons,
Mut,
Ref,
MutRef,
}
#[derive(Debug)]
pub enum FunctionBody {
EqualsBody(Expression),
BlockBody(BlockStatement),
AliasBody(Identifier),
}
#[derive(Debug)]
pub struct FunctionDeclaration {
pub is_public: bool,
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub identifier: Identifier,
pub parameters: Parameters,
pub return_type: Option<ReturnType>,
pub body: FunctionBody,
}
#[derive(Debug)]
pub struct OperatorFunctionDeclaration {
pub is_public: bool,
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub operator: Operator,
pub parameters: Parameters,
pub return_type: Option<ReturnType>,
pub body: FunctionBody,
}
#[derive(Debug)]
pub struct PlatformFunctionDeclaration {
pub is_public: bool,
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub identifier: Identifier,
pub parameters: Parameters,
pub return_type: TypeUse,
}
#[derive(Debug)]
pub struct InterfaceFunctionDeclaration {
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub identifier: Identifier,
pub parameters: Parameters,
pub return_type: ReturnType,
}
#[derive(Debug)]
pub struct InterfaceOperatorFunctionDeclaration {
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub operator: Operator,
pub parameters: Parameters,
pub return_type: ReturnType,
}
// Type components
#[derive(Debug)]
pub enum TypeParameters {
Generic(GenericParameters),
Tuple(TupleParameters),
Function(FunctionTypeParameters),
}
#[derive(Debug)]
pub struct TupleParameters(pub Vec<Identifier>);
#[derive(Debug)]
pub struct FunctionTypeParameters {
pub parameters: Parameters,
pub return_type: TypeUse,
}
// Class components
#[derive(Debug)]
pub struct ClassConstructor(pub Vec<ClassConstructorParameter>);
#[derive(Debug)]
pub struct ClassConstructorParameter {
pub is_field: bool,
pub identifier: Identifier,
pub declared_type: TypeUse
}
#[derive(Debug)]
pub struct FieldDeclaration {
pub is_mutable: bool,
pub identifier: Identifier,
pub declared_type: TypeUse,
}
// Statements
#[derive(Debug)]
pub struct BlockStatement(pub Vec<Statement>);
#[derive(Debug)]
pub enum Statement {
BlockStatement(BlockStatement),
CallStatement(CallExpression),
AssignStatement(AssignExpression),
VariableDeclarationStatement(VariableDeclarationStatement),
AssignStatement(AssignStatement),
ReturnStatement(ReturnStatement),
IfStatement(IfStatement),
IfElseStatement(IfElseStatement),
WhileStatement(WhileStatement),
ForStatement(ForStatement),
}
#[derive(Debug)]
pub struct VariableDeclarationStatement {
is_mutable: bool,
identifier: Identifier,
declared_type: Option<TypeUse>,
initializer: Option<Expression>,
}
#[derive(Debug)]
pub struct AssignStatement(pub AssignmentExpression);
#[derive(Debug)]
pub struct ReturnStatement(pub Option<Expression>);
#[derive(Debug)]
pub struct IfStatement {
pub condition: Expression,
pub then_branch: BlockStatement,
}
#[derive(Debug)]
pub struct IfElseStatement {
pub condition: Expression,
pub then_branch: BlockStatement,
pub else_ifs: ElseIfs,
pub else_branch: BlockStatement,
}
#[derive(Debug)]
pub struct ElseIfs(pub Vec<IfStatement>);
#[derive(Debug)]
pub struct WhileStatement {
pub condition: Expression,
pub body: BlockStatement,
}
#[derive(Debug)]
pub struct ForStatement {
pub variable: Identifier,
pub iterator: Expression,
pub body: BlockStatement,
}
// Expressions
#[derive(Debug)]
pub enum Expression {
Binary(BinaryExpression),
Unary(UnaryExpression),
Assignment(Box<AssignmentExpression>),
Call(CallExpression),
Literal(Literal)
}
#[derive(Debug)]
pub struct BinaryExpression {
pub left: Box<Expression>,
pub operator: BinaryOperator,
pub right: Box<Expression>,
}
#[derive(Debug)]
pub struct UnaryExpression {
pub operator: UnaryOperator,
pub expression: Box<Expression>,
}
#[derive(Debug)]
pub struct AssignmentExpression {
identifier: Identifier,
expression: Expression,
}
#[derive(Debug)]
pub struct CallExpression {
receiver: Expression,
actuals_list: Vec<Expression>,
source_code_location: SourceCodeLocation,
}
impl CallExpression {
pub fn receiver(&self) -> &Expression {
&self.receiver
}
pub fn actuals_list(&self) -> &Vec<Expression> {
&self.actuals_list
}
pub fn source_code_location(&self) -> &SourceCodeLocation {
&self.source_code_location
}
pub callee: Box<Expression>,
pub arguments: CallArguments
}
#[derive(Debug)]
pub struct AssignExpression {
left: LValue,
right: Expression,
}
pub struct CallArguments(pub Vec<CallArgument>);
#[derive(Debug)]
pub enum Expression {
CallExpression(Box<CallExpression>),
AssignExpression(Box<AssignExpression>),
LValue(Box<LValue>),
Literal(Box<Literal>),
}
#[derive(Debug)]
pub enum LValue {
Fqn(Fqn),
}
pub struct CallArgument(pub Box<Expression>);
#[derive(Debug)]
pub enum Literal {
@ -261,9 +512,3 @@ pub enum Literal {
StringLiteral(String),
BooleanLiteral(bool),
}
#[derive(Debug)]
pub struct Parameter {
identifier: Identifier,
declared_type: Option<TypeUse>,
}

959
src/ast/unparse.rs Normal file
View File

@ -0,0 +1,959 @@
use crate::ast::*;
macro_rules! to_unparse_vec {
( $nodes:expr ) => {
$nodes
.iter()
.map(|node| node as &dyn Unparse)
.collect::<Vec<&dyn Unparse>>()
};
}
macro_rules! unparse_contained_declarations {
( $declarations:expr, $buf:expr ) => {
if !$declarations.is_empty() {
write!($buf, "{{\n")?;
unparse_list($buf, "\n\n", &to_unparse_vec!($declarations));
write!($buf, "\n}}")?;
}
};
}
macro_rules! unparse_ok {
() => {
Ok(())
};
}
pub trait Unparse {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result;
}
pub trait ListUnparse: Unparse {
fn prefix() -> &'static str {
""
}
fn separator() -> &'static str;
fn suffix() -> &'static str {
""
}
fn inner(&self) -> Vec<&dyn Unparse>;
}
impl<T: ListUnparse> Unparse for T {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
write!(buf, "{}", Self::prefix())?;
unparse_list(buf, Self::separator(), &self.inner())?;
write!(buf, "{}", Self::suffix())?;
unparse_ok!()
}
}
fn unparse_list(
buf: &mut dyn std::fmt::Write,
sep: &str,
items: &[&dyn Unparse],
) -> std::fmt::Result {
for (i, item) in items.iter().enumerate() {
item.unparse(buf)?;
if i < items.len() - 1 {
write!(buf, "{}", sep)?;
}
}
Ok(())
}
fn unparse_comma_list(buf: &mut dyn std::fmt::Write, items: &[&dyn Unparse]) -> std::fmt::Result {
unparse_list(buf, ", ", items)
}
/* Implementations */
/* Operators */
impl Unparse for Operator {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use Operator::*;
match self {
Binary(op) => op.unparse(buf),
Unary(op) => op.unparse(buf),
}
}
}
impl Unparse for BinaryOperator {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use BinaryOperator::*;
match self {
Or => write!(buf, "||"),
And => write!(buf, "&&"),
EqualTo => write!(buf, "=="),
NotEqualTo => write!(buf, "!="),
Greater => write!(buf, ">"),
Less => write!(buf, "<"),
GreaterEqual => write!(buf, ">="),
LessEqual => write!(buf, "<="),
Add => write!(buf, "+"),
Subtract => write!(buf, "-"),
Multiply => write!(buf, "*"),
Divide => write!(buf, "/"),
Modulo => write!(buf, "%"),
LeftShift => write!(buf, "<<"),
RightShift => write!(buf, ">>"),
}
}
}
impl Unparse for UnaryOperator {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use UnaryOperator::*;
match self {
Not => write!(buf, "!"),
Negative => write!(buf, "-"),
PlusPlus => write!(buf, "++"),
MinusMinus => write!(buf, "--"),
CallOp => write!(buf, "()"),
Spread => write!(buf, "..."),
}
}
}
/* Names */
impl Unparse for Identifier {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
write!(buf, "{}", self.name)
}
}
impl ListUnparse for Fqn {
fn separator() -> &'static str {
"::"
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.identifiers)
}
}
/* Generic Parameters */
impl ListUnparse for GenericParameters {
fn prefix() -> &'static str {
"<"
}
fn separator() -> &'static str {
", "
}
fn suffix() -> &'static str {
">"
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl Unparse for GenericParameter {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.identifier.unparse(buf)
}
}
/* Generic arguments */
impl ListUnparse for GenericArguments {
fn prefix() -> &'static str {
"<"
}
fn separator() -> &'static str {
", "
}
fn suffix() -> &'static str {
">"
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl Unparse for GenericArgument {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.fqn.unparse(buf)
}
}
/* TypeUse and components */
impl Unparse for TypeUse {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.fqn.unparse(buf)?;
if let Some(type_arguments) = &self.arguments {
type_arguments.unparse(buf)?;
}
unparse_ok!()
}
}
impl Unparse for TypeArguments {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use TypeArguments::*;
match self {
Generics(generic_arguments) => generic_arguments.unparse(buf),
Tuple(tuple_arguments) => tuple_arguments.unparse(buf),
Function(function_type_arguments) => function_type_arguments.unparse(buf),
}
}
}
impl ListUnparse for TupleArguments {
fn prefix() -> &'static str {
"("
}
fn separator() -> &'static str {
", "
}
fn suffix() -> &'static str {
")"
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl Unparse for FunctionTypeArguments {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.parameters.unparse(buf)?;
write!(buf, " ")?;
self.return_type.unparse(buf)?;
unparse_ok!()
}
}
/* Function components */
impl ListUnparse for Parameters {
fn prefix() -> &'static str {
"("
}
fn separator() -> &'static str {
", "
}
fn suffix() -> &'static str {
")"
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl Unparse for Parameter {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.identifier.unparse(buf)?;
write!(buf, ": ")?;
self.type_use.unparse(buf)?;
unparse_ok!()
}
}
impl Unparse for ReturnType {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
write!(buf, "-> ")?;
self.type_use.unparse(buf)?;
if !self.references.is_empty() {
self.references.unparse(buf)?;
}
unparse_ok!()
}
}
impl ListUnparse for References {
fn prefix() -> &'static str {
"ref "
}
fn separator() -> &'static str {
", "
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl Unparse for Reference {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.identifier.unparse(buf)
}
}
/* Input parameters and arguments */
impl Unparse for DelegateOrIdentifier {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use DelegateOrIdentifier::*;
match self {
Delegate => write!(buf, "delegate"),
Identifier(identifier) => identifier.unparse(buf),
}
}
}
impl ListUnparse for InputParameters {
fn prefix() -> &'static str {
"|"
}
fn separator() -> &'static str {
", "
}
fn suffix() -> &'static str {
"|"
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl ListUnparse for InputArguments {
fn prefix() -> &'static str {
"|"
}
fn separator() -> &'static str {
", "
}
fn suffix() -> &'static str {
"|"
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl Unparse for InputArgument {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.lhs.unparse(buf)?;
write!(buf, " = ")?;
self.rhs.unparse(buf)?;
unparse_ok!()
}
}
/* Where guards */
impl ListUnparse for WhereGuards {
fn prefix() -> &'static str {
"where "
}
fn separator() -> &'static str {
", "
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl Unparse for WhereGuard {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.identifier.unparse(buf)?;
write!(buf, " : ")?;
self.implements.unparse(buf)?;
unparse_ok!()
}
}
/* Implements */
impl ListUnparse for ImplementsList {
fn prefix() -> &'static str {
": "
}
fn separator() -> &'static str {
" + "
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
/* Top-level construct */
impl Unparse for CompilationUnit {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if let Some(namespace) = &self.namespace {
write!(buf, "ns ")?;
namespace.unparse(buf)?;
write!(buf, "\n\n")?;
}
unparse_list(buf, "\n\n", &to_unparse_vec!(self.declarations))?;
unparse_ok!()
}
}
/* Declarations allowed in each level */
impl Unparse for ModuleLevelDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use ModuleLevelDeclaration::*;
match self {
Type(type_declaration) => type_declaration.unparse(buf),
Module(module_declaration) => module_declaration.unparse(buf),
Interface(interface_declaration) => interface_declaration.unparse(buf),
Class(class_declaration) => class_declaration.unparse(buf),
Function(function_declaration) => function_declaration.unparse(buf),
PlatformFunction(platform_function_declaration) => {
platform_function_declaration.unparse(buf)
}
}
}
}
impl Unparse for InterfaceLevelDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use InterfaceLevelDeclaration::*;
match self {
Type(type_declaration) => type_declaration.unparse(buf),
Module(module_declaration) => module_declaration.unparse(buf),
Interface(interface_declaration) => interface_declaration.unparse(buf),
Class(class_declaration) => class_declaration.unparse(buf),
Function(interface_function_declaration) => interface_function_declaration.unparse(buf),
OperatorFunction(interface_operator_function_declaration) => {
interface_operator_function_declaration.unparse(buf)
}
}
}
}
impl Unparse for ClassLevelDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use ClassLevelDeclaration::*;
match self {
Type(type_declaration) => type_declaration.unparse(buf),
Module(module_declaration) => module_declaration.unparse(buf),
Interface(interface_declaration) => interface_declaration.unparse(buf),
Class(class_declaration) => class_declaration.unparse(buf),
Function(function_declaration) => function_declaration.unparse(buf),
OperatorFunction(operator_function_declaration) => {
operator_function_declaration.unparse(buf)
}
PlatformFunction(platform_function_declaration) => {
platform_function_declaration.unparse(buf)
}
Field(field_declaration) => field_declaration.unparse(buf),
}
}
}
/* Declarations */
impl Unparse for TypeDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if self.is_public {
write!(buf, "pub ")?;
}
write!(buf, "type ")?;
self.identifier.unparse(buf)?;
write!(buf, " ")?;
if let Some(type_parameters) = &self.parameters {
type_parameters.unparse(buf)?;
write!(buf, " ")?;
}
self.where_guards.unparse(buf)?;
write!(buf, "= ")?;
self.rhs.unparse(buf)?;
Ok(())
}
}
impl Unparse for ModuleDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if self.is_public {
write!(buf, "pub ")?;
}
write!(buf, "mod ")?;
self.identifier.unparse(buf)?;
unparse_contained_declarations!(self.declarations, buf);
unparse_ok!()
}
}
impl Unparse for InterfaceDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if self.is_public {
write!(buf, "pub ")?;
}
write!(buf, "int ")?;
self.identifier.unparse(buf)?;
if !self.generics.is_empty() {
self.generics.unparse(buf)?;
write!(buf, " ")?;
}
if !self.inputs.is_empty() {
self.inputs.unparse(buf)?;
write!(buf, " ")?;
}
if !self.implements.is_empty() {
self.implements.unparse(buf)?;
write!(buf, " ")?;
}
if !self.where_guards.is_empty() {
self.where_guards.unparse(buf)?;
write!(buf, " ")?;
}
unparse_contained_declarations!(self.declarations, buf);
unparse_ok!()
}
}
impl Unparse for ClassDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if self.is_public {
write!(buf, "pub ")?;
}
write!(buf, "class ")?;
self.identifier.unparse(buf)?;
if !self.generics.is_empty() {
self.generics.unparse(buf)?;
}
if let Some(class_constructor) = &self.class_constructor {
class_constructor.unparse(buf)?;
}
write!(buf, " ")?;
if !self.implements.is_empty() {
self.implements.unparse(buf)?;
write!(buf, " ")?;
}
if !self.inputs.is_empty() {
self.inputs.unparse(buf)?;
write!(buf, " ")?;
}
if !self.where_guards.is_empty() {
self.where_guards.unparse(buf)?;
write!(buf, " ")?;
}
unparse_contained_declarations!(self.declarations, buf);
unparse_ok!()
}
}
/* Function declarations and components */
impl Unparse for FunctionModifier {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use FunctionModifier::*;
match self {
Static => write!(buf, "static"),
Cons => write!(buf, "cons"),
Mut => write!(buf, "mut"),
Ref => write!(buf, "ref"),
MutRef => write!(buf, "mut ref"),
}
}
}
impl Unparse for FunctionBody {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use FunctionBody::*;
match self {
EqualsBody(expression) => {
write!(buf, "= ")?;
expression.unparse(buf)
}
BlockBody(body) => body.unparse(buf),
AliasBody(identifier) => {
write!(buf, "alias ")?;
identifier.unparse(buf)
}
}
}
}
impl Unparse for FunctionDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if self.is_public {
write!(buf, "pub ")?;
}
if let Some(modifier) = &self.modifier {
modifier.unparse(buf)?;
write!(buf, " ")?;
}
write!(buf, "fn ")?;
self.generics.unparse(buf)?;
write!(buf, " ")?;
self.identifier.unparse(buf)?;
self.parameters.unparse(buf)?;
write!(buf, " ")?;
if let Some(return_type) = &self.return_type {
return_type.unparse(buf)?;
write!(buf, " ")?;
}
self.body.unparse(buf)?;
unparse_ok!()
}
}
impl Unparse for OperatorFunctionDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if self.is_public {
write!(buf, "pub ")?;
}
if let Some(modifier) = &self.modifier {
modifier.unparse(buf)?;
write!(buf, " ")?;
}
self.operator.unparse(buf)?;
write!(buf, " ")?;
self.parameters.unparse(buf)?;
write!(buf, " ")?;
if let Some(return_type) = &self.return_type {
return_type.unparse(buf)?;
write!(buf, " ")?;
}
self.body.unparse(buf)?;
unparse_ok!()
}
}
impl Unparse for PlatformFunctionDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if self.is_public {
write!(buf, "pub ")?;
}
write!(buf, "platform fn ")?;
if !self.generics.is_empty() {
self.generics.unparse(buf)?;
write!(buf, " ")?;
}
self.identifier.unparse(buf)?;
self.parameters.unparse(buf)?;
write!(buf, " ")?;
self.return_type.unparse(buf)?;
unparse_ok!()
}
}
impl Unparse for InterfaceFunctionDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if let Some(modifier) = &self.modifier {
modifier.unparse(buf)?;
write!(buf, " ")?;
}
if !self.generics.is_empty() {
self.parameters.unparse(buf)?;
write!(buf, " ")?;
}
self.identifier.unparse(buf)?;
self.parameters.unparse(buf)?;
write!(buf, " ")?;
self.return_type.unparse(buf)?;
unparse_ok!()
}
}
impl Unparse for InterfaceOperatorFunctionDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if let Some(modifier) = &self.modifier {
modifier.unparse(buf)?;
write!(buf, " ")?;
}
write!(buf, "op ")?;
if !self.generics.is_empty() {
self.generics.unparse(buf)?;
write!(buf, " ")?;
}
self.operator.unparse(buf)?;
write!(buf, " ")?;
self.parameters.unparse(buf)?;
write!(buf, " ")?;
self.return_type.unparse(buf)?;
unparse_ok!()
}
}
/* Type components */
impl Unparse for TypeParameters {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use TypeParameters::*;
match self {
Generic(generic_parameters) => generic_parameters.unparse(buf),
Tuple(tuple_parameters) => tuple_parameters.unparse(buf),
Function(function_type_parameters) => function_type_parameters.unparse(buf),
}
}
}
impl ListUnparse for TupleParameters {
fn prefix() -> &'static str {
"("
}
fn separator() -> &'static str {
", "
}
fn suffix() -> &'static str {
")"
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl Unparse for FunctionTypeParameters {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.parameters.unparse(buf)?;
write!(buf, " ")?;
self.return_type.unparse(buf)?;
unparse_ok!()
}
}
/* Class components */
impl ListUnparse for ClassConstructor {
fn prefix() -> &'static str {
"("
}
fn separator() -> &'static str {
", "
}
fn suffix() -> &'static str {
")"
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl Unparse for ClassConstructorParameter {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if self.is_field {
write!(buf, "fld ")?;
}
self.identifier.unparse(buf)?;
write!(buf, ": ")?;
self.declared_type.unparse(buf)?;
unparse_ok!()
}
}
impl Unparse for FieldDeclaration {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
if self.is_mutable {
write!(buf, "mut ")?;
}
self.identifier.unparse(buf)?;
write!(buf, ": ")?;
self.declared_type.unparse(buf)?;
unparse_ok!()
}
}
/* Statements */
impl ListUnparse for BlockStatement {
fn prefix() -> &'static str {
"{\n"
}
fn separator() -> &'static str {
"\n"
}
fn suffix() -> &'static str {
"\n}"
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl Unparse for Statement {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
use Statement::*;
match self {
BlockStatement(statement) => statement.unparse(buf),
CallStatement(call_expression) => call_expression.unparse(buf),
VariableDeclarationStatement(declaration) => declaration.unparse(buf),
AssignStatement(assign_statement) => assign_statement.unparse(buf),
ReturnStatement(return_expression) => return_expression.unparse(buf),
IfStatement(if_statement) => if_statement.unparse(buf),
IfElseStatement(if_else_statement) => if_else_statement.unparse(buf),
WhileStatement(while_statement) => while_statement.unparse(buf),
ForStatement(for_statement) => for_statement.unparse(buf),
}?;
write!(buf, "\n")
}
}
impl Unparse for VariableDeclarationStatement {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
write!(buf, "let ")?;
if self.is_mutable {
write!(buf, "mut ")?;
}
self.identifier.unparse(buf)?;
if let Some(declared_type) = &self.declared_type {
write!(buf, ": ")?;
declared_type.unparse(buf)?;
}
if let Some(initializer) = &self.initializer {
write!(buf, " = ")?;
initializer.unparse(buf)?;
}
unparse_ok!()
}
}
impl Unparse for AssignStatement {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.0.unparse(buf)
}
}
impl Unparse for ReturnStatement {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
write!(buf, "return")?;
if let Some(expression) = &self.0 {
write!(buf, " ")?;
expression.unparse(buf)?;
}
unparse_ok!()
}
}
impl Unparse for IfStatement {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
write!(buf, "if ")?;
self.condition.unparse(buf)?;
write!(buf, " {{\n")?;
self.then_branch.unparse(buf)?;
write!(buf, "\n}}")?;
unparse_ok!()
}
}
impl Unparse for IfElseStatement {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
write!(buf, "if ")?;
self.condition.unparse(buf)?;
write!(buf, " ")?;
self.then_branch.unparse(buf)?;
write!(buf, " ")?;
self.else_ifs.unparse(buf)?;
write!(buf, "else ")?;
self.else_branch.unparse(buf)?;
unparse_ok!()
}
}
impl Unparse for ElseIfs {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
for if_statement in &self.0 {
write!(buf, " else ")?;
if_statement.unparse(buf)?;
write!(buf, " ")?;
}
unparse_ok!()
}
}
impl Unparse for WhileStatement {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
write!(buf, "while ")?;
self.condition.unparse(buf)?;
write!(buf, " ")?;
self.body.unparse(buf)?;
unparse_ok!()
}
}
impl Unparse for ForStatement {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
write!(buf, "for ")?;
self.variable.unparse(buf)?;
write!(buf, " in ")?;
self.iterator.unparse(buf)?;
write!(buf, " ")?;
self.body.unparse(buf)?;
unparse_ok!()
}
}
/* Expressions */
impl Unparse for AssignmentExpression {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.identifier.unparse(buf)?;
write!(buf, " = ")?;
self.expression.unparse(buf)?;
unparse_ok!()
}
}
impl Unparse for Expression {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
todo!()
}
}
impl Unparse for CallExpression {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.callee.unparse(buf)?;
self.arguments.unparse(buf)?;
unparse_ok!()
}
}
impl ListUnparse for CallArguments {
fn prefix() -> &'static str {
"("
}
fn separator() -> &'static str {
", "
}
fn suffix() -> &'static str {
")"
}
fn inner(&self) -> Vec<&dyn Unparse> {
to_unparse_vec!(self.0)
}
}
impl Unparse for CallArgument {
fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result {
self.0.unparse(buf)
}
}

View File

@ -1,78 +1,78 @@
// Top-level constructs
CompilationUnit = { SOI ~ Namespace? ~ ModuleLevelDeclaration* ~ EOI }
Namespace = { "ns" ~ FullyQualifiedName }
// Keywords
Ns = { "ns" }
TypeKw = { "type" }
Mod = { "mod" }
Int = { "int" }
ClassKw = { "class" }
Platform = { "platform" }
Pub = { "pub" }
Fld = { "fld" }
Impl = { "impl" }
Mut = { "mut" }
Cons = { "cons" }
Static = { "static" }
Ref = { "ref" }
Def = { "def" }
Where = { "where" }
Infer = { "infer" }
Void = { "Void" }
Delegate = { "delegate" }
Let = { "let" }
Fn = { "fn" }
Op = { "op" }
CommonDeclaration = { Interface | Class | Module | Function | OperatorFunction }
ModuleLevelDeclaration = { Declare? ~ Public? ~ CommonDeclaration }
InterfaceLevelDeclaration = { CommonDeclaration }
ClassLevelDeclaration = { Declare? ~ Public? ~ ( CommonDeclaration | ClassMember ) }
// Module
Module = { "mod" ~ Identifier ~ "{" ~ ModuleLevelDeclaration* ~ "}" }
// Interface
Interface = { "int" ~ Identifier ~ GenericParameters? ~ ExtendsList? ~ ( "{" ~ InterfaceLevelDeclaration* ~ "}" )? }
// Class
Class = { "class" ~ Identifier ~ GenericParameters? ~ ClassConstructor? ~ ExtendsList? ~ ( "{" ~ ClassLevelDeclaration* ~ "}" )? }
ClassMember = { Field? ~ Identifier ~ TypeAnnotation? }
// Class Constructor
ClassConstructor = { "(" ~ ClassMemberList? ~ ")" }
ClassMemberList = { ClassMember ~ ( "," ~ ClassMember )* }
// Various Keywords
Declare = { "decl" }
Public = { "pub" }
Field = { "fld" }
Implementation = { "impl" }
Mutable = { "mut" }
Consume = { "cons" }
Reference = { "ref" }
Define = { "def" }
// Fqn and identifier
FullyQualifiedName = { Identifier ~ ( "::" ~ Identifier )* }
Identifier = @{ IdentifierStartChar ~ IdentifierChar* }
IdentifierStartChar = { 'a'..'z' | 'A'..'Z' | "_" }
IdentifierChar = { 'a'..'z' | 'A'..'Z' | '0'..'9' | "_" }
// Type constructs
ExtendsList = { ":" ~ TypeUse ~ ( "+" ~ TypeUse )* }
TypeAnnotation = { ":" ~ TypeUse }
TypeUse = { FullyQualifiedName ~ GenericArguments? }
// Generic arguments given to a TypeUse or function calls
GenericArguments = { "<" ~ FullyQualifiedName ~ ( "," ~ FullyQualifiedName )* ~ ">" }
// Generic parameters (for when types are declared)
GenericParameters = { "<" ~ Identifier ~ ( "," ~ Identifier )* ~ ">" }
// Function
Function = { ( Implementation | Define )?
~ ( Consume | Mutable )?
~ Reference?
~ "fn"
~ GenericParameters?
~ Identifier
~ "(" ~ Parameters? ~ ")"
~ ReturnType?
~ ( FunctionAlias | FunctionEqualsBody | BlockStatement )?
// Keywords as a rule (for preventing identifiers with keywords, etc.)
Keyword = {
Ns
| TypeKw
| Mod
| Int
| ClassKw
| Platform
| Pub
| Fld
| Impl
| Mut
| Cons
| Static
| Ref
| Def
| Where
| Infer
| Void
| Delegate
| Let
| Fn
| Op
}
ReturnType = { "->" ~ Reference? ~ TypeUse }
FunctionAlias = { "alias" ~ FullyQualifiedName }
OperatorFunction = { ( Implementation | Define )?
~ ( Consume | Mutable )?
~ Reference?
~ "op"
~ Operator
~ "(" ~ Parameters? ~ ")"
~ ReturnType?
~ ( FunctionAlias | FunctionEqualsBody | BlockStatement )?
}
Operator = { Or
// Symbols
Ellipsis = { "..." }
Underscore = { "_" }
// Operators
Or = { "||" }
And = { "&&" }
EqualTo = { "==" }
NotEqualTo = { "!=" }
Greater = { ">" }
Less = { "<" }
GreaterEqual = { ">=" }
LessEqual = { "<=" }
Add = { "+" }
Subtract = { "-" }
Multiply = { "*" }
Divide = { "/" }
Modulo = { "%" }
Not = { "!" }
Negative = { "-" }
PlusPlus = { "++" }
MinusMinus = { "--" }
CallOp = { "()" }
Spread = { Ellipsis }
Operator = {
Or
| And
| EqualTo
| NotEqualTo
@ -85,93 +85,691 @@ Operator = { Or
| Multiply
| Divide
| Modulo
| Not
| Negative
| PlusPlus
| MinusMinus
| CallOp
| Spread
}
CallOp = { "()" }
// Commonly shared constructs
Parameters = { Parameter ~ ( "," ~ Parameter )* }
Parameter = { Identifier ~ TypeAnnotation? }
FullyQualifiedName = {
Identifier
~ ( "::" ~ Identifier )*
}
FunctionEqualsBody = { "=" ~ Expression }
Identifier = @{
( Keyword ~ IdentifierChar | !Keyword ~ IdentifierStartChar )
~ IdentifierChar*
}
IdentifierStartChar = {
'a'..'z'
| 'A'..'Z'
| "_"
}
IdentifierChar = {
'a'..'z'
| 'A'..'Z'
| '0'..'9'
| "_"
}
// In general:
// Arguments = usage
// Parameters = declaration
TypeUse = {
FullyQualifiedName
~ (
GenericArguments ~ InputArguments?
| TupleGenericArguments
| FunctionGenericArguments ~ FunctionInputArguments?
| InputArguments
)?
}
GenericArguments = {
"<"
~ FullyQualifiedName
~ ( "," ~ FullyQualifiedName )*
~ ">"
}
InputArguments = {
"|"
~ (
InputArgument
~ ( "," ~ InputArgument )*
)?
~ "|"
}
InputArgument = {
Identifier
~ ( "=" ~ Identifier )
}
TupleGenericArguments = {
"("
~ (
FullyQualifiedName
~ ( "," ~ FullyQualifiedName )*
)?
~ ")"
}
FunctionGenericArguments = {
TupleGenericArguments
~ ReturnTypeGenericArgument
~ FunctionInputArguments?
}
ReturnTypeGenericArgument = {
"->"
~ ( Void | FullyQualifiedName )
~ RefList?
}
RefList = {
Ref
~ Identifier
~ ( "," ~ Identifier )*
}
FunctionInputArguments = {
"|"
~ (
FunctionInputArgument
~ ( "," ~ FunctionInputArgument )*
)?
~ "|"
}
FunctionInputArgument = {
( Delegate | Identifier )
~ ( "=" ~ Identifier )
}
// Generic Parameters
GenericParameters = {
"<"
~ Identifier
~ ( "," ~ Identifier )*
~ ">"
}
InputParameters = {
"|"
~ InputParameter
~ ( "," ~ InputParameter )*
~ "|"
}
InputParameter = {
Identifier
~ ":"
~ TypeUse
}
TupleGenericParameters = {
"("
~ (
Identifier
~ ( "," ~ Identifier )*
)?
~ ")"
}
FunctionGenericParameters = {
TupleGenericParameters
~ FunctionGenericParameterReturnType
}
FunctionGenericParameterReturnType = {
"->"
~ ( Void | Identifier )
~ RefList?
}
FunctionInputParameters = {
"|"
~ FunctionInputParameter
~ ( "," ~ FunctionInputParameter )*
~ "|"
}
FunctionInputParameter = {
( Delegate | Identifier )
~ ":"
~ TypeUse
}
ImplementsList = {
":"
~ TypeUse
~ ( "+" ~ TypeUse )
}
WhereGuards = {
Where
~ WhereGuard
~ ( "," ~ WhereGuard )*
}
WhereGuard = {
Identifier
~ ImplementsList
}
// Top-level constructs
CompilationUnit = {
SOI
~ Namespace?
~ ModuleLevelDeclaration*
~ EOI
}
Namespace = {
Ns
~ FullyQualifiedName
}
// Organizational declarations
ModuleLevelDeclaration = {
Type
| Module
| Interface
| Class
| FunctionDefinition
| PlatformFunction
}
InterfaceLevelDeclaration = {
Type
| Module
| Interface
| Class
| InterfaceFunction
| InterfaceDefaultFunction
| InterfaceOperatorFunction
| InterfaceDefaultOperatorFunction
}
ClassLevelDeclaration = {
Type
| Module
| Interface
| Class
| FunctionDefinition
| OperatorFunctionDefinition
| PlatformFunction
| Field
}
// Main organizational constructs
Type = {
Pub?
~ TypeKw
~ Identifier
~ GenericParameters?
~ TypeWhereGuards?
~ "="
~ TypeUse
}
Module = {
Pub?
~ Mod
~ Identifier
~ "{" ~ ModuleLevelDeclaration* ~ "}"
}
Interface = {
Pub?
~ Int
~ Identifier
~ InterfaceGenericParametersAndInputs?
~ ImplementsList?
~ WhereGuards?
~ ( "{" ~ InterfaceLevelDeclaration* ~ "}" )?
}
Class = {
Pub?
~ ClassKw
~ Identifier
~ GenericParameters?
~ ClassConstructor?
~ ImplementsList?
~ InputArguments?
~ WhereGuards?
~ ( "{" ~ ClassLevelDeclaration* ~ "}" )?
}
// Type
TypeWhereGuards = {
Where
~ TypeWhereGuard
~ ( "," ~ TypeWhereGuard )*
}
TypeWhereGuard = {
Identifier
~ ":"
~ TypeTypeUse
~ ( "+" ~ TypeTypeUse )*
}
TypeTypeUse = {
FullyQualifiedName
~ TypeTypeArguments?
}
TypeTypeArguments = {
TypeGenericArguments
| TypeGenericFunctionArguments
| TypeGenericTupleArguments
}
TypeGenericArguments = {
"<"
~ TypeGenericArgument
~ ( "," ~ TypeGenericArgument )*
~ ">"
}
TypeGenericArgument = {
Underscore
| FullyQualifiedName
| ( Infer ~ Identifier )
}
TypeGenericTupleArguments = {
"("
~ (
TypeGenericTupleArgument
~ ( "," ~ TypeGenericTupleArgument )*
)?
~ ")"
}
TypeGenericTupleArgument = {
Underscore
| FullyQualifiedName
| ( Infer ~ Identifier )
| ( Ellipsis ~ Underscore )
| ( Ellipsis ~ Infer ~ Identifier )
}
TypeGenericFunctionArguments = {
TypeGenericTupleArguments
~ TypeGenericArguments?
~ TypeFunctionReturnType
}
TypeFunctionReturnType = {
"->"
~ ( Void | FullyQualifiedName )
~ RefList?
}
// Interface
InterfaceGenericParametersAndInputs = {
GenericParameters ~ InputParameters?
| TupleGenericParameters
| FunctionGenericParameters ~ FunctionInputParameters?
| InputParameters
}
InterfaceFunction = {
(
Static
| Cons
| ( Mut ~ Ref? )
)?
~ Fn
~ GenericParameters?
~ Identifier
~ Parameters
~ ReturnType
~ WhereGuards?
}
InterfaceDefaultFunction = {
Def
~ (
Static
| Cons
| ( Mut ~ Ref? )
)?
~ Fn
~ GenericParameters?
~ Identifier
~ Parameters
~ ReturnType
~ WhereGuards?
~ FunctionBody
}
InterfaceOperatorFunction = {
(
Cons
| ( Mut ~ Ref? )
)?
~ Op
~ Operator
~ Parameters
~ ReturnType
~ RefList?
~ WhereGuards? // TODO: decide if we want this for interface op functions
}
InterfaceDefaultOperatorFunction = {
Def
~ (
Cons
| ( Mut ~ Ref? )
)?
~ Op
~ Operator
~ Parameters
~ ReturnType
~ RefList?
~ WhereGuards?
~ FunctionBody
}
// Class constructs
ClassConstructor = {
"("
~ DataMember
~ ( "," ~ DataMember )*
~ ")"
}
DataMember = {
Property
| Field
}
Property = {
Mut?
~ Identifier
~ ":"
~ TypeUse
}
Field = {
Mut?
~ Fld
~ Identifier
~ ":"
~ TypeUse
}
// Function constructs
FunctionModifier = {
Static
| Cons
| Mut? Ref?
}
FunctionDefinition = {
Pub?
~ FunctionModifier
~ Fn
~ GenericParameters?
~ Identifier
~ Parameters
~ ReturnType?
~ FunctionBody
}
OperatorFunctionDefinition = {
Pub?
~ FunctionModifier
~ Op
~ Operator
~ Parameters
~ ReturnType?
~ FunctionBody
}
PlatformFunction = {
Pub?
~ FunctionModifier
~ Platform
~ Fn
~ GenericParameters
~ Identifier
~ Parameters
~ ReturnType
}
Parameters = {
"("
~ (
Parameter
~ ( "," ~ Parameter )*
)?
~ ")"
}
Parameter = {
Identifier
~ ":"
~ TypeUse
}
ReturnType = {
"->"
~ ( Void | TypeUse )
~ RefList?
}
FunctionBody = {
FunctionEqualsBody
| FunctionBlockBody
| FunctionAliasBody
}
FunctionEqualsBody = {
"="
~ Expression
}
FunctionBlockBody = {
"{"
~ Statement*
~ "}"
}
FunctionAliasBody = {
"alias"
~ Identifier
}
// Statements
BlockStatement = { "{" ~ Statement* ~ "}" }
Statement = { VariableDeclaration | CallExpression | AssignmentExpression }
VariableDeclaration = { "let" ~ Mutable? ~ Identifier ~ TypeAnnotation? ~ ( "=" ~ Expression )? }
BlockStatement = {
"{"
~ Statement*
~ "}"
}
Statement = {
BlockStatement
| VariableDeclaration
| AssignmentExpression
}
VariableDeclaration = {
Let
~ Mut?
~ Identifier
~ ( ":" ~ TypeUse )?
~ ( "=" ~ Expression )?
}
// Expressions
Expression = { OrExpression }
OrExpression = { AndExpression ~ ( Or ~ AndExpression )* }
AndExpression = { EqualityExpression ~ ( And ~ EqualityExpression )* }
Or = { "||" }
And = { "&&" }
OrExpression = {
AndExpression
~ ( Or ~ Expression )*
}
EqualityExpression = { ComparisonExpression ~ ( ( EqualTo | NotEqualTo ) ~ ComparisonExpression )* }
EqualTo = { "==" }
NotEqualTo = { "!=" }
AndExpression = {
EqualityExpression
~ ( And ~ Expression )*
}
ComparisonExpression = { AdditiveExpression ~ ( ( Greater | Less | GreaterEqual | LessEqual ) ~ AdditiveExpression )* }
Greater = { ">" }
Less = { "<" }
GreaterEqual = { ">=" }
LessEqual = { "<=" }
EqualityExpression = {
ComparisonExpression
~ (
( EqualTo | NotEqualTo )
~ Expression
)*
}
AdditiveExpression = { MultiplicativeExpression ~ ( ( Add | Subtract ) ~ MultiplicativeExpression )* }
Add = { "+" }
Subtract = { "-" }
ComparisonExpression = {
AdditiveExpression
~ (
( Greater | Less | GreaterEqual | LessEqual )
~ Expression
)*
}
MultiplicativeExpression = { UnaryExpression ~ ( ( Multiply | Divide | Modulo ) ~ UnaryExpression )* }
Multiply = { "*" }
Divide = { "/" }
Modulo = { "%" }
AdditiveExpression = {
MultiplicativeExpression
~ (
( Add | Subtract )
~ Expression
)*
}
UnaryExpression = { ( Not | Negative )* ~ PrimaryExpression ~ ( Call | ( PlusPlus | MinusMinus ) )* }
Not = { "!" }
Negative = { "-" }
PlusPlus = { "++" }
MinusMinus = { "--" }
MultiplicativeExpression = {
SpreadExpression
~ (
( Multiply | Divide | Modulo )
~ Expression
)*
}
PrimaryExpression = { Literal | ObjectAccess | ParenthesizedExpression }
ParenthesizedExpression = { "(" ~ Expression ~ ")" }
SpreadExpression = {
UnaryExpression
~ Spread
~ Expression
}
UnaryExpression = {
( Not | Negative )*
~ PrimaryExpression
~ ( ( NoParenthesesCall | ParenthesesCall )+ | ( PlusPlus | MinusMinus ) )?
}
// Call
CallExpression = { PrimaryExpression ~ Call+ }
Call = { GenericArguments? ~ CallArguments }
ExpressionList = { Expression ~ ( "," ~ Expression )* }
CallArguments = {
( "(" ~ ExpressionList? ~ ")" )
| ExpressionList
PrimaryExpression = {
Literal
| ObjectAccess
| ParenthesizedExpression
}
ParenthesizedExpression = {
"("
~ Expression
~ ")"
}
// Calls
ParenthesesCall = {
TurboFish?
~ "("
~ ExpressionList?
~ ")"
}
NoParenthesesCall = {
TurboFish?
~ ExpressionList
}
TurboFish = {
"::"
~ GenericArguments
}
ExpressionList = {
Expression
~ ( "," ~ Expression )*
}
// Assignment
AssignmentExpression = { ObjectAccess ~ "=" ~ Expression }
AssignmentExpression = {
ObjectAccess
~ "="
~ Expression
}
// Object
ObjectAccess = { FullyQualifiedName ~ ( "." ~ Identifier )* }
ObjectAccess = {
FullyQualifiedName
~ ( "." ~ Identifier )*
}
// Literals
Literal = { NumberLiteral | StringLiteral | BooleanLiteral | NullLiteral }
Literal = {
NumberLiteral
| StringLiteral
| BooleanLiteral
}
NumberLiteral = { LongLiteral | IntLiteral }
NumberLiteral = {
LongLiteral
| IntLiteral
| DoubleLiteral
}
IntLiteral = { NumberBase }
LongLiteral = ${ NumberBase ~ "L" }
NumberBase = { DecimalBase | BinaryBase | HexadecimalBase }
DoubleLiteral = ${ DecimalBase ~ "." ~ Digit+ }
NumberBase = {
DecimalBase
| BinaryBase
| HexadecimalBase
}
DecimalBase = @{ DecimalStartDigit ~ Digit* }
BinaryBase = @{ "0b" ~ Digit* }
DecimalStartDigit = { '1'..'9' }
Digit = { '0'..'9'+ }
HexadecimalBase = @{ "0x" ~ HexadecimalDigit+ }
HexadecimalDigit = { '0'..'9' | 'a'..'f' }
StringLiteral = ${ "\"" ~ StringInner ~ "\"" }
StringInner = @{ StringChar* }
StringChar = {
!( "\"" | "\\" ) ~ ANY
| "\\" ~ ( "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" )
@ -180,6 +778,4 @@ StringChar = {
BooleanLiteral = { "true" | "false" }
NullLiteral = { "null" }
WHITESPACE = _{ " " | "\t" | "\n" | "\r" }