Skip to content

Commit 7050f5c

Browse files
Add support for type function statements (#333)
1 parent 8e134da commit 7050f5c

File tree

43 files changed

+1014
-12
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1014
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44

5+
* add support for type functions ([#333](https://github.com/seaofvoices/darklua/pull/333))
56
* add support for property modifiers in table types (like `read` in a type like `{ read name: string }`) ([#332](https://github.com/seaofvoices/darklua/pull/332))
67

78
## 0.17.3

src/ast_converter.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,36 @@ impl<'a> AstConverter<'a> {
852852
.into(),
853853
);
854854
}
855+
ConvertWork::MakeTypeFunctionStatement {
856+
statement,
857+
export_token,
858+
} => {
859+
let builder = self.convert_function_body_attributes(
860+
statement.function_body(),
861+
self.convert_token(statement.function_token())?,
862+
)?;
863+
864+
let mut name = Identifier::new(statement.function_name().token().to_string());
865+
let mut type_token = None;
866+
let mut export = None;
867+
868+
if self.hold_token_data {
869+
name.set_token(self.convert_token(statement.function_name())?);
870+
type_token = Some(self.convert_token(statement.type_token())?);
871+
export = export_token
872+
.map(|token| self.convert_token(token))
873+
.transpose()?;
874+
}
875+
876+
let mut type_function_statement =
877+
builder.into_type_function_statement(name, type_token, export);
878+
879+
if export_token.is_some() {
880+
type_function_statement.set_exported();
881+
}
882+
883+
self.statements.push(type_function_statement.into());
884+
}
855885
ConvertWork::MakeLocalAssignStatement { statement } => {
856886
let variables = statement
857887
.names()
@@ -1547,6 +1577,22 @@ impl<'a> AstConverter<'a> {
15471577
});
15481578
self.push_function_body_work(local_function.body());
15491579
}
1580+
ast::Stmt::TypeFunction(type_function) => {
1581+
self.work_stack
1582+
.push(ConvertWork::MakeTypeFunctionStatement {
1583+
statement: type_function,
1584+
export_token: None,
1585+
});
1586+
self.push_function_body_work(type_function.function_body());
1587+
}
1588+
ast::Stmt::ExportedTypeFunction(type_function) => {
1589+
self.work_stack
1590+
.push(ConvertWork::MakeTypeFunctionStatement {
1591+
statement: type_function.type_function(),
1592+
export_token: Some(type_function.export_token()),
1593+
});
1594+
self.push_function_body_work(type_function.type_function().function_body());
1595+
}
15501596
ast::Stmt::NumericFor(numeric_for) => {
15511597
self.work_stack.push(ConvertWork::MakeNumericForStatement {
15521598
statement: numeric_for,
@@ -2866,6 +2912,10 @@ enum ConvertWork<'a> {
28662912
type_declaration: &'a ast::luau::TypeDeclaration,
28672913
export_token: Option<&'a tokenizer::TokenReference>,
28682914
},
2915+
MakeTypeFunctionStatement {
2916+
statement: &'a ast::luau::TypeFunction,
2917+
export_token: Option<&'a tokenizer::TokenReference>,
2918+
},
28692919
MakePrefixFromExpression {
28702920
prefix: &'a ast::Prefix,
28712921
},

src/generator/dense.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,42 @@ impl LuaGenerator for DenseLuaGenerator {
637637
self.write_type(statement.get_type());
638638
}
639639

640+
fn write_type_function_statement(&mut self, function: &nodes::TypeFunctionStatement) {
641+
if function.is_exported() {
642+
self.push_str("export");
643+
}
644+
self.push_str("type");
645+
self.push_str("function");
646+
647+
self.write_identifier(function.get_identifier());
648+
649+
if let Some(generics) = function.get_generic_parameters() {
650+
self.write_function_generics(generics);
651+
}
652+
653+
self.push_char('(');
654+
655+
let parameters = function.get_parameters();
656+
self.write_function_parameters(
657+
parameters,
658+
function.is_variadic(),
659+
function.get_variadic_type(),
660+
);
661+
self.push_char(')');
662+
663+
if let Some(return_type) = function.get_return_type() {
664+
self.push_char(':');
665+
self.write_function_return_type(return_type);
666+
}
667+
668+
let block = function.get_block();
669+
670+
if !block.is_empty() {
671+
self.write_block(block);
672+
}
673+
self.push_str("end");
674+
}
675+
640676
fn write_false_expression(&mut self, _token: &Option<nodes::Token>) {
641677
self.push_str("false");
642678
}

src/generator/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub trait LuaGenerator {
3737
Repeat(statement) => self.write_repeat_statement(statement),
3838
While(statement) => self.write_while_statement(statement),
3939
TypeDeclaration(statement) => self.write_type_declaration_statement(statement),
40+
TypeFunction(statement) => self.write_type_function_statement(statement),
4041
}
4142
}
4243

@@ -53,6 +54,7 @@ pub trait LuaGenerator {
5354
fn write_repeat_statement(&mut self, repeat: &nodes::RepeatStatement);
5455
fn write_while_statement(&mut self, while_statement: &nodes::WhileStatement);
5556
fn write_type_declaration_statement(&mut self, statement: &nodes::TypeDeclarationStatement);
57+
fn write_type_function_statement(&mut self, statement: &nodes::TypeFunctionStatement);
5658

5759
fn write_variable(&mut self, variable: &nodes::Variable) {
5860
use nodes::Variable::*;
@@ -883,6 +885,18 @@ mod $mod_name {
883885
),
884886
));
885887

888+
snapshot_node!($mod_name, $generator, type_function, write_type_function_statement => (
889+
empty => TypeFunctionStatement::from_name("nothing", Block::default()),
890+
empty_exported => TypeFunctionStatement::from_name("nothing", Block::default())
891+
.export(),
892+
empty_with_parameter => TypeFunctionStatement::from_name("nothing", Block::default())
893+
.with_parameter("param"),
894+
empty_with_parameters_and_return_type => TypeFunctionStatement::from_name("nothing", Block::default())
895+
.with_parameter("param")
896+
.with_return_type(Type::from(true)),
897+
));
898+
899+
886900
snapshot_node!($mod_name, $generator, if_statement, write_statement => (
887901
empty => IfStatement::create(false, Block::default()),
888902
empty_with_empty_else => IfStatement::create(false, Block::default())

src/generator/readable.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ enum StatementType {
1616
Repeat,
1717
While,
1818
TypeDeclaration,
19+
TypeFunction,
1920
Return,
2021
Break,
2122
Continue,
@@ -38,6 +39,7 @@ impl From<&nodes::Statement> for StatementType {
3839
Repeat(_) => Self::Repeat,
3940
While(_) => Self::While,
4041
TypeDeclaration(_) => Self::TypeDeclaration,
42+
TypeFunction(_) => Self::TypeFunction,
4143
}
4244
}
4345
}
@@ -871,6 +873,45 @@ impl LuaGenerator for ReadableLuaGenerator {
871873
self.write_type(statement.get_type());
872874
}
873875

876+
fn write_type_function_statement(&mut self, function: &nodes::TypeFunctionStatement) {
877+
self.push_can_add_new_line(false);
878+
if function.is_exported() {
879+
self.push_str("export");
880+
}
881+
self.push_str("type function ");
882+
self.write_identifier(function.get_identifier());
883+
884+
if let Some(generics) = function.get_generic_parameters() {
885+
self.write_function_generics(generics);
886+
}
887+
888+
self.raw_push_char('(');
889+
890+
self.pop_can_add_new_line();
891+
892+
let parameters = function.get_parameters();
893+
self.write_function_parameters(
894+
parameters,
895+
function.is_variadic(),
896+
function.get_variadic_type(),
897+
);
898+
self.raw_push_char(')');
899+
900+
if let Some(return_type) = function.get_return_type() {
901+
self.write_function_return_type_suffix(return_type);
902+
}
903+
904+
let block = function.get_block();
905+
906+
if block.is_empty() {
907+
self.raw_push_str(" end");
908+
} else {
909+
self.push_new_line();
910+
self.indent_and_write_block(block);
911+
self.push_str("end");
912+
}
913+
}
914+
874915
fn write_false_expression(&mut self, _token: &Option<nodes::Token>) {
875916
self.push_str("false");
876917
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
source: src/generator/mod.rs
3+
expression: generator.into_string()
4+
---
5+
type function nothing()end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
source: src/generator/mod.rs
3+
expression: generator.into_string()
4+
---
5+
export type function nothing()end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
source: src/generator/mod.rs
3+
expression: generator.into_string()
4+
---
5+
type function nothing(param)end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
source: src/generator/mod.rs
3+
expression: generator.into_string()
4+
---
5+
type function nothing(param):true end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
source: src/generator/mod.rs
3+
expression: generator.into_string()
4+
---
5+
type function nothing() end

0 commit comments

Comments
 (0)