Compare commits

...

2 Commits

Author SHA1 Message Date
Jesse Brault
8c802f2a15 Sketching July 2025. 2025-08-01 07:47:56 -05:00
Jesse Brault
6f727e1cdf Refactor UseStatement to an enum type; remove UseStatementLast. 2025-05-29 21:37:07 -05:00
16 changed files with 461 additions and 325 deletions

View File

@ -0,0 +1,22 @@
fn main()
var x = 42
let cl = { i: Int ->
let result = x + i
x += 1
result
}
println cl(0) // 42
println cl(0) // 43
println cl(0) // 44
end
fn main()
var x = 42
fn cl(i: Int): Int
let result = x + 1
x += 1
result
end
println cl(0) // 42
println cl(1) // 42
end

View File

@ -0,0 +1,32 @@
pub hkt Functor[Self<T>]
fn <U> map(f: fn (t: T) -> U) -> Self<U>
end
pub int Iterable<T>
fn iter() -> Iterator<T>
end
pub int Iterator<T> = () -> Option<T>
pub enum Option<T> : Functor[Self<T>]
Some(T),
None;
fn unwrap() -> T
self is Some(t) ? t : throw Exception('Empty Option')
end
fn expect(msg: String) -> T
self is Some(t) ? t : throw Exception(msg)
end
impl Functor
fn <U> map(f: fn (t: T) -> U) -> Self<U>
self is Some(t) ? Some(f(t)) : None
end
end
static fn lift(t: T) -> Self<T>
Some(t)
end
end

View File

@ -0,0 +1,14 @@
int Greeter
fn greet(): Void
end
class MyGreeter(greeting: String) : Greeter
impl fn greet()
println greeting
end
end
fn main()
let g: Greeter = MyGreeter("Hello, World!")
g.greet()
end

View File

@ -0,0 +1,39 @@
fn main(args: Array<String>)
if args[0] == 'greet' then
println 'Hello!'
end
end
fn main(args: Array<String>)
args.each { println it }
end
fn main(args: Array<String>)
if args.find { it == 'greet' } then
println 'There was a greet arg'
end
end
// longer
fn main(args: Array<String>)
let findIndexResult: Option<Int> = args.findIndex { it == 'greet' }
if findIndexResult.isSome() then
let index: Int = findIndex.unwrap()
println "greet arg was index ${index}"
end
end
// shorter with destructuring
fn main(args: Array<String>)
if let Some(greetIndex) = args.findIndex { it == 'greet' } then
println "greet arg was index ${greetIndex}"
end
end
fn main(args: Array<String>)
let parsed: CliArgs = std::cli::parse(args)
let greetingCount = parsed.get::<Int>('--count', '-c').orElse(1)
if let Some(greeting) = parsed.get('greeting', 'g') then
greetingCount.times { println greeting }
end
end

View File

@ -0,0 +1,105 @@
pub int Display
fn toString() -> String
end
pub int LazyDisplay
fn toLazyString() -> DString
end
pub int DString : Display
parts: Array<DStringPart>
end
pub enum DStringPart
Constant(String),
Display(Display),
Lazy(Fn<Display>)
end
#internal
class DStringImpl(parts) : DString
cachedEval: Option<String>
canCache: Option<Boolean>
fn getCanCache() -> Boolean
for part in parts do
if part is Lazy then return false end
end
true
end
impl Display
pub fn toString() -> String
if cachedEval is Some(s) then
return s
end
if canCache is None then
canCache = Some(getCanCache())
end
// Note the groovy-like property getter
if canCache.truthy then
cachedEval = Some(
parts.reduce('') { acc, part ->
let partAsString = match part as
Constant(s) => s,
Display(d) => d.toString(),
Lazy(f) => throw DumbProgrammerException(
'Cannot cache when parts contains a Lazy.'
)
end
acc + partAsString
}
)
cachedEval.unwrap()
else
parts.reduce('') { acc, part ->
let partAsString = match part as
Constant(s) => s,
Display(d) => d.toString(),
Lazy(f) => f().toString()
end
acc + partAsString
}
end
end
end
end
// Special "extension" implementation of Option for all T where T : Boolean
pub int HasTruth
fn isTruthy() -> Boolean
end
impl HasTruth for Option<T> where T is Boolean
pub fn isTruthy() -> Boolean
self is Some(b) ? b : false
end
end
// some other file
use std::extensions::HasTruth[Option<Boolean>]
fn maybeSomeOrNone -> Option<Boolean>
Some(true)
end
fn main()
let o = maybeSomeOrNone()
if o.truthy then
println "It's truthy!"
else
println "It's falsy..."
end
end
fn stringDemo() -> Void
let plain = 'Hello, World!'
let x = 42
let withDisplay = "Hello! x is $x"
let withLazy = "Hello! x is ${ x + 42 }"
println plain // Hello, World!
println withDisplay // Hello! x is 42
println withLazy // Hello! x is 84
x += 42
println withLazy // Hello! x is 126
end

View File

@ -0,0 +1,41 @@
pub trait HasTruth
fn isTruthy() -> Boolean
def fn isFalsy() -> Boolean = !self.truthy
end
pub trait Functor[Self<T>]
fn <U> map(f: fn (t: T) -> U) -> Self<U>
end
pub trait Lift[Self<T>]
static fn lift(t: T) -> Self<T>
end
pub trait Applicative[Self<T>, U, V] : Functor[Self] + Lift[Self] where T is fn (u: U) -> V
fn apply(us: Self<U>) -> Self<V>
end
pub trait Monad[Self<T>] : Functor[Self] + Lift[Self]
fn <U> flatMap(f: fn (t: T) -> Self<U>) -> Self<U>
end
// Traits as higher-kinded types
// - Cannot be used as concrete types, casted, etc.
// - Cannot be constructed/instantiated
// - Imports are different:
// ```
// use std::core::Option
// use std::trait::Monad[Option<*>] // bring in Monad for all Option<*>
// ```
// - Once imported, fns are in scope
// - Can also be looked-up 'dictionary' style:
// ```
// use std::trait::HasTruth[Option<Boolean>]
//
// fn main()
// let maybeTruthy: Option<Boolean> = someOtherApiCall()
// if HasTruth[maybeTruthy].isTruthy() then
// println "It's truthy."
// end
// ```

View File

@ -427,29 +427,37 @@ fn build_namespace(file_id: usize, namespace_pair: Pair<Rule>) -> FullyQualified
fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseStatement { fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseStatement {
let as_span = use_statement_pair.as_span(); let as_span = use_statement_pair.as_span();
let range = Range {
start: as_span.start(),
end: as_span.end(),
};
let mut inner = use_statement_pair.into_inner(); let mut inner = use_statement_pair.into_inner();
let inner_length = inner.len(); let inner_length = inner.len();
inner.next().unwrap(); // use inner.next().unwrap(); // use
let mut identifiers = vec![]; let mut prefixes = vec![];
let mut last = None; let mut built: Option<UseStatement> = None;
for (i, inner_pair) in inner.into_iter().enumerate() { for (i, inner_pair) in inner.into_iter().enumerate() {
if i != inner_length - 2 { if i != inner_length - 2 {
identifiers.push(Box::new(expect_and_use( prefixes.push(inner_pair.as_str());
file_id,
inner_pair,
Rule::Identifier,
build_identifier,
)));
} else { } else {
last = Some(Box::new(match inner_pair.as_rule() { built = Some(match inner_pair.as_rule() {
Rule::Identifier => { Rule::Identifier => UseStatement::Concrete(ConcreteUseStatement::new(
UseStatementLast::Identifier(Box::new(build_identifier(file_id, inner_pair))) prefixes.iter().map(|s| s.to_string()).collect(),
} vec![Box::new(expect_and_use(
Rule::Star => UseStatementLast::Star, file_id,
Rule::UseList => UseStatementLast::Identifiers( inner_pair,
Rule::Identifier,
build_identifier,
))],
file_id,
range,
)),
Rule::UseList => UseStatement::Concrete(ConcreteUseStatement::new(
prefixes.iter().map(|s| s.to_string()).collect(),
inner_pair inner_pair
.into_inner() .into_inner()
.map(|identifier_pair| { .map(|identifier_pair| {
@ -461,21 +469,20 @@ fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseSta
)) ))
}) })
.collect(), .collect(),
), file_id,
range,
)),
Rule::Star => UseStatement::Star(StarUseStatement::new(
prefixes.iter().map(|s| s.to_string()).collect(),
file_id,
range,
)),
_ => unreachable!(), _ => unreachable!(),
})); });
} }
} }
UseStatement::new( built.unwrap()
identifiers,
last.unwrap(),
file_id,
Range {
start: as_span.start(),
end: as_span.end(),
},
)
} }
fn build_module_level_declaration(file_id: usize, pair: Pair<Rule>) -> ModuleLevelDeclaration { fn build_module_level_declaration(file_id: usize, pair: Pair<Rule>) -> ModuleLevelDeclaration {

View File

@ -88,7 +88,7 @@ pub enum NodeRef<'a> {
pub trait NodeInner { pub trait NodeInner {
fn children(&self) -> Vec<NodeRef>; fn children(&self) -> Vec<NodeRef>;
fn as_node_ref(&self) -> NodeRef; fn as_node_ref(&self) -> NodeRef;
} }
@ -96,7 +96,7 @@ impl NodeInner for Identifier {
fn children(&self) -> Vec<NodeRef> { fn children(&self) -> Vec<NodeRef> {
vec![] vec![]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::Identifier(self) NodeRef::Identifier(self)
} }
@ -109,7 +109,7 @@ impl NodeInner for FullyQualifiedName {
.map(|id| NodeRef::Identifier(*id)) .map(|id| NodeRef::Identifier(*id))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::FullyQualifiedName(self) NodeRef::FullyQualifiedName(self)
} }
@ -126,7 +126,7 @@ impl NodeInner for TypeUse {
TypeUse::Function(function_type_use) => function_type_use.children(), TypeUse::Function(function_type_use) => function_type_use.children(),
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::TypeUse(self) NodeRef::TypeUse(self)
} }
@ -145,7 +145,7 @@ impl NodeInner for PrimitiveTypeUse {
_ => vec![], _ => vec![],
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::PrimitiveTypeUse(self) NodeRef::PrimitiveTypeUse(self)
} }
@ -158,7 +158,7 @@ impl NodeInner for InterfaceOrClassTypeUse {
children.push(NodeRef::GenericArguments(self.generics())); children.push(NodeRef::GenericArguments(self.generics()));
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::InterfaceOrClassTypeUse(self) NodeRef::InterfaceOrClassTypeUse(self)
} }
@ -168,7 +168,7 @@ impl NodeInner for TupleTypeUse {
fn children(&self) -> Vec<NodeRef> { fn children(&self) -> Vec<NodeRef> {
vec![NodeRef::TupleArguments(self.arguments())] vec![NodeRef::TupleArguments(self.arguments())]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::TupleTypeUse(self) NodeRef::TupleTypeUse(self)
} }
@ -182,7 +182,7 @@ impl NodeInner for FunctionTypeUse {
NodeRef::ReturnType(self.return_type()), NodeRef::ReturnType(self.return_type()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::FunctionTypeUse(self) NodeRef::FunctionTypeUse(self)
} }
@ -195,7 +195,7 @@ impl NodeInner for GenericArguments {
.map(|type_use| NodeRef::TypeUse(*type_use)) .map(|type_use| NodeRef::TypeUse(*type_use))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::GenericArguments(self) NodeRef::GenericArguments(self)
} }
@ -208,7 +208,7 @@ impl NodeInner for GenericParameters {
.map(|id| NodeRef::Identifier(*id)) .map(|id| NodeRef::Identifier(*id))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::GenericParameters(self) NodeRef::GenericParameters(self)
} }
@ -221,7 +221,7 @@ impl NodeInner for TupleArguments {
.map(|type_use| NodeRef::TypeUse(*type_use)) .map(|type_use| NodeRef::TypeUse(*type_use))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::TupleArguments(self) NodeRef::TupleArguments(self)
} }
@ -234,7 +234,7 @@ impl NodeInner for ImplementsList {
.map(|type_use| NodeRef::TypeUse(*type_use)) .map(|type_use| NodeRef::TypeUse(*type_use))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ImplementsList(self) NodeRef::ImplementsList(self)
} }
@ -247,7 +247,7 @@ impl NodeInner for Parameters {
.map(|parameter| NodeRef::Parameter(*parameter)) .map(|parameter| NodeRef::Parameter(*parameter))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::Parameters(self) NodeRef::Parameters(self)
} }
@ -260,7 +260,7 @@ impl NodeInner for Parameter {
NodeRef::TypeUse(self.type_use()), NodeRef::TypeUse(self.type_use()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::Parameter(self) NodeRef::Parameter(self)
} }
@ -273,7 +273,7 @@ impl NodeInner for ReturnType {
NodeRef::References(self.references()), NodeRef::References(self.references()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ReturnType(self) NodeRef::ReturnType(self)
} }
@ -286,7 +286,7 @@ impl NodeInner for References {
.map(|identifier| NodeRef::Identifier(*identifier)) .map(|identifier| NodeRef::Identifier(*identifier))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::References(self) NodeRef::References(self)
} }
@ -310,7 +310,7 @@ impl NodeInner for CompilationUnit {
); );
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::CompilationUnit(self) NodeRef::CompilationUnit(self)
} }
@ -319,25 +319,18 @@ impl NodeInner for CompilationUnit {
impl NodeInner for UseStatement { impl NodeInner for UseStatement {
fn children(&self) -> Vec<NodeRef> { fn children(&self) -> Vec<NodeRef> {
let mut children = vec![]; let mut children = vec![];
children.extend( match self {
self.identifiers() UseStatement::Concrete(concrete_use_statement) => children.extend(
.iter() concrete_use_statement
.map(|identifier| NodeRef::Identifier(*identifier)), .identifiers()
);
match self.last() {
UseStatementLast::Identifier(identifier) => {
children.push(NodeRef::Identifier(identifier))
}
UseStatementLast::Identifiers(identifiers) => children.extend(
identifiers
.iter() .iter()
.map(|identifier| NodeRef::Identifier(identifier.clone())), .map(|identifier| NodeRef::Identifier(*identifier))
), ),
UseStatementLast::Star => {} UseStatement::Star(_) => {}
} }
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::UseStatement(self) NodeRef::UseStatement(self)
} }
@ -356,7 +349,7 @@ impl NodeInner for ModuleLevelDeclaration {
} }
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ModuleLevelDeclaration(self) NodeRef::ModuleLevelDeclaration(self)
} }
@ -375,7 +368,7 @@ impl NodeInner for InterfaceLevelDeclaration {
} }
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::InterfaceLevelDeclaration(self) NodeRef::InterfaceLevelDeclaration(self)
} }
@ -399,7 +392,7 @@ impl NodeInner for ClassLevelDeclaration {
Field(field_declaration) => field_declaration.children(), Field(field_declaration) => field_declaration.children(),
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ClassLevelDeclaration(self) NodeRef::ClassLevelDeclaration(self)
} }
@ -416,7 +409,7 @@ impl NodeInner for ModuleDeclaration {
); );
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ModuleDeclaration(self) NodeRef::ModuleDeclaration(self)
} }
@ -435,7 +428,7 @@ impl NodeInner for InterfaceDeclaration {
); );
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::InterfaceDeclaration(self) NodeRef::InterfaceDeclaration(self)
} }
@ -457,7 +450,7 @@ impl NodeInner for ClassDeclaration {
); );
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ClassDeclaration(self) NodeRef::ClassDeclaration(self)
} }
@ -473,7 +466,7 @@ impl NodeInner for FunctionDefinition {
NodeRef::FunctionBody(self.body()), NodeRef::FunctionBody(self.body()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::FunctionDefinition(self) NodeRef::FunctionDefinition(self)
} }
@ -488,7 +481,7 @@ impl NodeInner for OperatorFunctionDefinition {
NodeRef::FunctionBody(self.body()), NodeRef::FunctionBody(self.body()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::OperatorFunctionDefinition(self) NodeRef::OperatorFunctionDefinition(self)
} }
@ -503,7 +496,7 @@ impl NodeInner for PlatformFunctionDeclaration {
NodeRef::ReturnType(self.return_type()), NodeRef::ReturnType(self.return_type()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::PlatformFunctionDeclaration(self) NodeRef::PlatformFunctionDeclaration(self)
} }
@ -522,7 +515,7 @@ impl NodeInner for InterfaceFunctionDeclaration {
} }
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::InterfaceFunctionDeclaration(self) NodeRef::InterfaceFunctionDeclaration(self)
} }
@ -540,7 +533,7 @@ impl NodeInner for InterfaceOperatorFunctionDeclaration {
} }
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::InterfaceOperatorFunctionDeclaration(self) NodeRef::InterfaceOperatorFunctionDeclaration(self)
} }
@ -554,7 +547,7 @@ impl NodeInner for FunctionBody {
Self::Alias(identifier) => vec![NodeRef::Identifier(identifier.as_ref())], Self::Alias(identifier) => vec![NodeRef::Identifier(identifier.as_ref())],
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::FunctionBody(self) NodeRef::FunctionBody(self)
} }
@ -567,7 +560,7 @@ impl NodeInner for ClassConstructor {
.map(|parameter| NodeRef::ClassConstructorParameter(*parameter)) .map(|parameter| NodeRef::ClassConstructorParameter(*parameter))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ClassConstructor(self) NodeRef::ClassConstructor(self)
} }
@ -580,7 +573,7 @@ impl NodeInner for ClassConstructorParameter {
Self::Field(field_declaration) => field_declaration.children(), Self::Field(field_declaration) => field_declaration.children(),
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ClassConstructorParameter(self) NodeRef::ClassConstructorParameter(self)
} }
@ -593,7 +586,7 @@ impl NodeInner for PropertyDeclaration {
NodeRef::TypeUse(self.declared_type()), NodeRef::TypeUse(self.declared_type()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::PropertyDeclaration(self) NodeRef::PropertyDeclaration(self)
} }
@ -606,7 +599,7 @@ impl NodeInner for FieldDeclaration {
NodeRef::TypeUse(self.declared_type()), NodeRef::TypeUse(self.declared_type()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::FieldDeclaration(self) NodeRef::FieldDeclaration(self)
} }
@ -625,7 +618,7 @@ impl NodeInner for BlockStatement {
} }
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::BlockStatement(self) NodeRef::BlockStatement(self)
} }
@ -648,7 +641,7 @@ impl NodeInner for Statement {
ForStatement(for_statement) => for_statement.children(), ForStatement(for_statement) => for_statement.children(),
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::Statement(self) NodeRef::Statement(self)
} }
@ -666,7 +659,7 @@ impl NodeInner for VariableDeclarationStatement {
} }
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::VariableDeclarationStatement(self) NodeRef::VariableDeclarationStatement(self)
} }
@ -679,7 +672,7 @@ impl NodeInner for AssignStatement {
NodeRef::Expression(self.rhs()), NodeRef::Expression(self.rhs()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::AssignStatement(self) NodeRef::AssignStatement(self)
} }
@ -689,7 +682,7 @@ impl NodeInner for CallStatement {
fn children(&self) -> Vec<NodeRef> { fn children(&self) -> Vec<NodeRef> {
vec![NodeRef::Expression(self.expression())] vec![NodeRef::Expression(self.expression())]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::CallStatement(self) NodeRef::CallStatement(self)
} }
@ -703,7 +696,7 @@ impl NodeInner for ReturnStatement {
vec![] vec![]
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ReturnStatement(self) NodeRef::ReturnStatement(self)
} }
@ -716,7 +709,7 @@ impl NodeInner for IfStatement {
NodeRef::BlockStatement(self.then_block()), NodeRef::BlockStatement(self.then_block()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::IfStatement(self) NodeRef::IfStatement(self)
} }
@ -732,7 +725,7 @@ impl NodeInner for IfElseStatement {
} }
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::IfElseStatement(self) NodeRef::IfElseStatement(self)
} }
@ -745,7 +738,7 @@ impl NodeInner for ElseIfs {
.map(|statement| NodeRef::IfStatement(statement)) .map(|statement| NodeRef::IfStatement(statement))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ElseIfs(self) NodeRef::ElseIfs(self)
} }
@ -755,7 +748,7 @@ impl NodeInner for ElseBlock {
fn children(&self) -> Vec<NodeRef> { fn children(&self) -> Vec<NodeRef> {
vec![NodeRef::BlockStatement(self.block_statement())] vec![NodeRef::BlockStatement(self.block_statement())]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ElseBlock(self) NodeRef::ElseBlock(self)
} }
@ -768,7 +761,7 @@ impl NodeInner for WhileStatement {
NodeRef::BlockStatement(self.body()), NodeRef::BlockStatement(self.body()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::WhileStatement(self) NodeRef::WhileStatement(self)
} }
@ -782,7 +775,7 @@ impl NodeInner for ForStatement {
NodeRef::BlockStatement(self.body()), NodeRef::BlockStatement(self.body()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ForStatement(self) NodeRef::ForStatement(self)
} }
@ -803,7 +796,7 @@ impl NodeInner for Expression {
Closure(closure) => closure.children(), Closure(closure) => closure.children(),
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::Expression(self) NodeRef::Expression(self)
} }
@ -817,7 +810,7 @@ impl NodeInner for TernaryExpression {
NodeRef::Expression(self.false_expression()), NodeRef::Expression(self.false_expression()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::TernaryExpression(self) NodeRef::TernaryExpression(self)
} }
@ -830,7 +823,7 @@ impl NodeInner for BinaryExpression {
NodeRef::Expression(self.right()), NodeRef::Expression(self.right()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::BinaryExpression(self) NodeRef::BinaryExpression(self)
} }
@ -840,7 +833,7 @@ impl NodeInner for PrefixExpression {
fn children(&self) -> Vec<NodeRef> { fn children(&self) -> Vec<NodeRef> {
vec![NodeRef::Expression(self.expression())] vec![NodeRef::Expression(self.expression())]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::PrefixExpression(self) NodeRef::PrefixExpression(self)
} }
@ -850,7 +843,7 @@ impl NodeInner for SuffixExpression {
fn children(&self) -> Vec<NodeRef> { fn children(&self) -> Vec<NodeRef> {
vec![NodeRef::Expression(self.expression())] vec![NodeRef::Expression(self.expression())]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::SuffixExpression(self) NodeRef::SuffixExpression(self)
} }
@ -866,7 +859,7 @@ impl NodeInner for CallExpression {
children.push(NodeRef::CallArguments(self.arguments())); children.push(NodeRef::CallArguments(self.arguments()));
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::CallExpression(self) NodeRef::CallExpression(self)
} }
@ -876,7 +869,7 @@ impl NodeInner for TurboFish {
fn children(&self) -> Vec<NodeRef> { fn children(&self) -> Vec<NodeRef> {
vec![NodeRef::GenericArguments(self.generics())] vec![NodeRef::GenericArguments(self.generics())]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::TurboFish(self) NodeRef::TurboFish(self)
} }
@ -889,7 +882,7 @@ impl NodeInner for CallArguments {
.map(|argument| NodeRef::CallArgument(*argument)) .map(|argument| NodeRef::CallArgument(*argument))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::CallArguments(self) NodeRef::CallArguments(self)
} }
@ -899,7 +892,7 @@ impl NodeInner for CallArgument {
fn children(&self) -> Vec<NodeRef> { fn children(&self) -> Vec<NodeRef> {
vec![NodeRef::Expression(self.expression())] vec![NodeRef::Expression(self.expression())]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::CallArgument(self) NodeRef::CallArgument(self)
} }
@ -920,7 +913,7 @@ impl NodeInner for Closure {
} }
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::Closure(self) NodeRef::Closure(self)
} }
@ -933,7 +926,7 @@ impl NodeInner for ClosureCaptures {
.map(|capture| NodeRef::ClosureCapture(*capture)) .map(|capture| NodeRef::ClosureCapture(*capture))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ClosureCaptures(self) NodeRef::ClosureCaptures(self)
} }
@ -943,7 +936,7 @@ impl NodeInner for ClosureCapture {
fn children(&self) -> Vec<NodeRef> { fn children(&self) -> Vec<NodeRef> {
vec![NodeRef::Identifier(self.identifier())] vec![NodeRef::Identifier(self.identifier())]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ClosureCapture(self) NodeRef::ClosureCapture(self)
} }
@ -956,7 +949,7 @@ impl NodeInner for ClosureParameters {
.map(|parameter| NodeRef::ClosureParameter(*parameter)) .map(|parameter| NodeRef::ClosureParameter(*parameter))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ClosureParameters(self) NodeRef::ClosureParameters(self)
} }
@ -971,7 +964,7 @@ impl NodeInner for ClosureParameter {
} }
children children
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ClosureParameter(self) NodeRef::ClosureParameter(self)
} }
@ -984,7 +977,7 @@ impl NodeInner for ObjectAccess {
NodeRef::ObjectNavigations(self.navigations()), NodeRef::ObjectNavigations(self.navigations()),
] ]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ObjectAccess(self) NodeRef::ObjectAccess(self)
} }
@ -997,7 +990,7 @@ impl NodeInner for ObjectNavigations {
.map(|navigation| NodeRef::ObjectNavigation(*navigation)) .map(|navigation| NodeRef::ObjectNavigation(*navigation))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ObjectNavigations(self) NodeRef::ObjectNavigations(self)
} }
@ -1010,7 +1003,7 @@ impl NodeInner for ObjectNavigation {
ObjectNavigation::Index(index_expression) => NodeRef::Expression(index_expression), ObjectNavigation::Index(index_expression) => NodeRef::Expression(index_expression),
}] }]
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::ObjectNavigation(self) NodeRef::ObjectNavigation(self)
} }
@ -1024,7 +1017,7 @@ impl NodeInner for Literal {
_ => vec![], _ => vec![],
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::Literal(self) NodeRef::Literal(self)
} }
@ -1037,7 +1030,7 @@ impl NodeInner for DString {
.map(|part| NodeRef::DStringPart(*part)) .map(|part| NodeRef::DStringPart(*part))
.collect() .collect()
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::DString(self) NodeRef::DString(self)
} }
@ -1050,7 +1043,7 @@ impl NodeInner for DStringPart {
_ => vec![], _ => vec![],
} }
} }
fn as_node_ref(&self) -> NodeRef { fn as_node_ref(&self) -> NodeRef {
NodeRef::DStringPart(self) NodeRef::DStringPart(self)
} }

View File

@ -1,75 +1,48 @@
use crate::ast::node::named::Named; use crate::ast::node::named::Named;
use crate::ast::node::names::Identifier; use crate::ast::node::names::Identifier;
use std::borrow::Cow;
use std::range::Range; use std::range::Range;
#[derive(Debug)] #[derive(Debug)]
pub struct UseStatement { pub enum UseStatement {
Concrete(ConcreteUseStatement),
Star(StarUseStatement),
}
#[derive(Debug)]
pub struct ConcreteUseStatement {
prefixes: Vec<String>,
identifiers: Vec<Box<Identifier>>, identifiers: Vec<Box<Identifier>>,
last: Box<UseStatementLast>,
file_id: usize, file_id: usize,
range: Range<usize>, range: Range<usize>,
} }
impl UseStatement { impl ConcreteUseStatement {
pub fn new( pub fn new(
prefixes: Vec<String>,
identifiers: Vec<Box<Identifier>>, identifiers: Vec<Box<Identifier>>,
last: Box<UseStatementLast>,
file_id: usize, file_id: usize,
range: Range<usize>, range: Range<usize>,
) -> Self { ) -> Self {
UseStatement { ConcreteUseStatement {
prefixes,
identifiers, identifiers,
last,
file_id, file_id,
range, range,
} }
} }
pub fn base_name(&self) -> Cow<'_, str> { pub fn prefixes(&self) -> &Vec<String> {
use UseStatementLast::*; &self.prefixes
if self.identifiers.is_empty() {
match self.last.as_ref() {
Identifier(_) => Cow::from(""),
Star | Identifiers(_) => panic!(), // should never get here because of grammar
}
} else if self.identifiers.len() == 1 {
self.identifiers[0].name()
} else {
let mut acc = String::new();
for (i, identifier) in self.identifiers.iter().enumerate() {
acc.push_str(&identifier.name());
if i != self.identifiers.len() - 1 {
acc.push_str("::");
}
}
Cow::from(acc)
}
} }
pub fn is_star(&self) -> bool { pub fn join_prefixes(&self) -> String {
match self.last.as_ref() { self.prefixes.join("::")
UseStatementLast::Star => true,
_ => false,
}
} }
pub fn identifiers(&self) -> Vec<&Identifier> { pub fn identifiers(&self) -> Vec<&Identifier> {
self.identifiers.iter().map(Box::as_ref).collect() self.identifiers.iter().map(Box::as_ref).collect()
} }
pub fn identifiers_mut(&mut self) -> Vec<&mut Identifier> {
self.identifiers.iter_mut().map(Box::as_mut).collect()
}
pub fn last(&self) -> &UseStatementLast {
&self.last
}
pub fn last_mut(&mut self) -> &mut UseStatementLast {
&mut self.last
}
pub fn file_id(&self) -> usize { pub fn file_id(&self) -> usize {
self.file_id self.file_id
} }
@ -80,8 +53,34 @@ impl UseStatement {
} }
#[derive(Debug)] #[derive(Debug)]
pub enum UseStatementLast { pub struct StarUseStatement {
Identifier(Box<Identifier>), prefixes: Vec<String>,
Identifiers(Vec<Box<Identifier>>), file_id: usize,
Star, range: Range<usize>,
}
impl StarUseStatement {
pub fn new(prefixes: Vec<String>, file_id: usize, range: Range<usize>) -> Self {
Self {
prefixes,
file_id,
range,
}
}
pub fn prefixes(&self) -> &Vec<String> {
&self.prefixes
}
pub fn join_prefixes(&self) -> String {
self.prefixes.join("::")
}
pub fn file_id(&self) -> usize {
self.file_id
}
pub fn range(&self) -> Range<usize> {
self.range
}
} }

View File

@ -320,6 +320,28 @@ impl PrettyPrint for CompilationUnit {
} }
} }
impl PrettyPrint for UseStatement {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.writeln_indented("UseStatement")?;
writer.increase_indent();
match self {
UseStatement::Concrete(concrete_use_statement) => {
writer.writeln_indented(&format!("ConcreteUseStatement(prefixes = {})", concrete_use_statement.join_prefixes()))?;
writer.increase_indent();
for identifier in concrete_use_statement.identifiers() {
identifier.pretty_print(writer)?;
}
writer.decrease_indent();
}
UseStatement::Star(star_use_statement) => {
writer.writeln_indented(&format!("StarUseStatement(prefixes = {})", star_use_statement.join_prefixes()))?;
}
}
writer.decrease_indent();
Ok(())
}
}
impl PrettyPrint for ModuleLevelDeclaration { impl PrettyPrint for ModuleLevelDeclaration {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
use crate::ast::node::level::ModuleLevelDeclaration::*; use crate::ast::node::level::ModuleLevelDeclaration::*;
@ -618,39 +640,6 @@ impl PrettyPrint for FieldDeclaration {
} }
} }
impl PrettyPrint for UseStatement {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.writeln_indented("UseStatement")?;
writer.increase_indent();
for identifier in self.identifiers() {
identifier.pretty_print(writer)?;
}
self.last().pretty_print(writer)?;
writer.decrease_indent();
Ok(())
}
}
impl PrettyPrint for UseStatementLast {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.writeln_indented("UseStatementLast")?;
writer.increase_indent();
match self {
UseStatementLast::Identifier(i) => i.pretty_print(writer)?,
UseStatementLast::Identifiers(is) => {
for i in is {
i.pretty_print(writer)?;
}
}
UseStatementLast::Star => {
writer.writeln_indented("Star")?;
}
}
writer.decrease_indent();
Ok(())
}
}
impl PrettyPrint for BlockStatement { impl PrettyPrint for BlockStatement {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> { fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.writeln_indented("BlockStatement")?; writer.writeln_indented("BlockStatement")?;

View File

@ -410,35 +410,28 @@ impl Unparse for CompilationUnit {
impl Unparse for UseStatement { impl Unparse for UseStatement {
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> { fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.write_indented("use ")?; writer.write_indented("use ")?;
for (i, identifier) in self.identifiers().iter().enumerate() {
identifier.unparse(writer)?;
if i != self.identifiers().len() - 2 {
// 2 because of use
writer.write("::")?;
}
}
self.last().unparse(writer)?;
Ok(())
}
}
impl Unparse for UseStatementLast {
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
match self { match self {
UseStatementLast::Star => writer.write("*"), UseStatement::Concrete(concrete_use_statement) => {
UseStatementLast::Identifiers(identifiers) => { writer.write(&format!("{}::", concrete_use_statement.join_prefixes()))?;
writer.write("{")?; let identifiers = concrete_use_statement.identifiers();
for (i, identifier) in identifiers.iter().enumerate() { if identifiers.len() == 1 {
identifier.unparse(writer)?; identifiers[0].unparse(writer)?;
if i != identifiers.len() - 1 { } else {
writer.write(", ")?; writer.write("{")?;
for (i, identifier) in identifiers.iter().enumerate() {
identifier.unparse(writer)?;
if i != identifiers.len() - 1 {
writer.write(", ")?;
}
} }
writer.write("}")?;
} }
writer.write("}")?; },
Ok(()) UseStatement::Star(star_use_statement) => {
writer.write(&format!("{}::*", star_use_statement.join_prefixes()))?;
} }
UseStatementLast::Identifier(i) => i.unparse(writer),
} }
Ok(())
} }
} }

View File

@ -364,21 +364,7 @@ fn gather_use_statement(
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
if use_statement.is_star() { todo!()
todo!()
}
let base_name = use_statement.base_name().to_string();
match use_statement.last_mut() {
UseStatementLast::Identifier(identifier) => {
handle_use_statement_import(symbol_table, &base_name, identifier, diagnostics)
}
UseStatementLast::Identifiers(identifiers) => {
for identifier in identifiers {
handle_use_statement_import(symbol_table, &base_name, identifier, diagnostics)
}
}
UseStatementLast::Star => panic!(),
}
} }
/* Declarations allowed in each level */ /* Declarations allowed in each level */

View File

@ -56,7 +56,6 @@ mod tests {
use super::*; use super::*;
use crate::ast::build::build_ast; use crate::ast::build::build_ast;
use crate::ast::children::NodeRef; use crate::ast::children::NodeRef;
use crate::ast::node::use_statement::UseStatementLast;
use crate::ast::walk::walk_depth_first; use crate::ast::walk::walk_depth_first;
use crate::parser::{DeimosParser, Rule}; use crate::parser::{DeimosParser, Rule};
use crate::std_core::add_std_core_symbols; use crate::std_core::add_std_core_symbols;
@ -126,25 +125,7 @@ mod tests {
panic!("{:?} does not have a saved symbol.", fqn) panic!("{:?} does not have a saved symbol.", fqn)
} }
} }
NodeRef::UseStatement(use_statement) => match use_statement.last() { NodeRef::UseStatement(use_statement) => match use_statement {
UseStatementLast::Identifier(identifier) => {
if identifier.saved_symbol().is_none() {
panic!(
"UseStatement {:?} does not have a saved symbol.",
identifier
)
}
}
UseStatementLast::Identifiers(identifiers) => {
for identifier in identifiers {
if identifier.saved_symbol().is_none() {
panic!(
"UseStatement {:?} does not have a saved symbol.",
identifier
)
}
}
}
_ => todo!(), _ => todo!(),
}, },
_ => {} _ => {}
@ -153,35 +134,7 @@ mod tests {
fn assert_resolved_symbols(compilation_unit: &CompilationUnit) { fn assert_resolved_symbols(compilation_unit: &CompilationUnit) {
walk_depth_first(compilation_unit, &mut |node_ref| match node_ref { walk_depth_first(compilation_unit, &mut |node_ref| match node_ref {
NodeRef::UseStatement(use_statement) => match use_statement.last() { NodeRef::UseStatement(use_statement) => match use_statement {
UseStatementLast::Identifier(identifier) => {
let use_statement_symbol = identifier
.saved_symbol()
.unwrap()
.unwrap_use_statement_symbol();
let borrowed = use_statement_symbol.borrow();
if borrowed.referenced_symbol().is_none() {
panic!(
"{:?} does not have a referenced symbol.",
use_statement_symbol
)
}
}
UseStatementLast::Identifiers(identifiers) => {
for identifier in identifiers {
let use_statement_symbol = identifier
.saved_symbol()
.unwrap()
.unwrap_use_statement_symbol();
let borrowed = use_statement_symbol.borrow();
if borrowed.referenced_symbol().is_none() {
panic!(
"{:?} does not have a referenced symbol.",
use_statement_symbol
)
}
}
}
_ => todo!(), _ => todo!(),
}, },
_ => {} _ => {}

View File

@ -260,36 +260,7 @@ fn resolve_use_statement(
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
let file_id = use_statement.file_id(); todo!()
let use_statement_range = use_statement.range();
let base_name = use_statement.base_name().to_string();
match use_statement.last_mut() {
UseStatementLast::Identifier(identifier) => {
handle_use_statement_identifier(
identifier.deref_mut(),
&base_name,
symbol_table,
diagnostics,
file_id,
use_statement_range,
);
}
UseStatementLast::Identifiers(identifiers) => {
for identifier in identifiers {
let identifier_range = identifier.range();
handle_use_statement_identifier(
identifier.deref_mut(),
&base_name,
symbol_table,
diagnostics,
file_id,
identifier_range,
)
}
}
UseStatementLast::Star => todo!("star imports"),
}
} }
/* Declarations allowed in each level */ /* Declarations allowed in each level */

View File

@ -28,15 +28,7 @@ impl SourceDefinition {
range: borrowed.range(), range: borrowed.range(),
} }
} }
#[deprecated(note = "Use identifier instead.")]
pub fn from_use_statement(use_statement: &UseStatement) -> Self {
SourceDefinition {
file_id: use_statement.file_id(),
range: use_statement.range(),
}
}
pub fn file_id(&self) -> usize { pub fn file_id(&self) -> usize {
self.file_id self.file_id
} }

View File

@ -333,6 +333,20 @@ Namespace = {
~ FullyQualifiedName ~ FullyQualifiedName
} }
UseStatement = {
Use
~ Identifier
~ ( "::" ~ Identifier )*
~ ( "::" ~ ( Star | UseList ) )?
}
UseList = {
"{"
~ Identifier
~ ( "," ~ Identifier )*
~ "}"
}
// Organizational declarations // Organizational declarations
ModuleLevelDeclaration = { ModuleLevelDeclaration = {
@ -523,20 +537,6 @@ Field = {
// Statements // Statements
UseStatement = {
Use
~ Identifier
~ ( "::" ~ Identifier )*
~ ( "::" ~ ( Star | UseList ) )?
}
UseList = {
"{"
~ Identifier
~ ( "," ~ Identifier )*
~ "}"
}
BlockStatement = { BlockStatement = {
"{" "{"
~ Statement* ~ Statement*