Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Named Arguments #625

Merged
merged 32 commits into from
Sep 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
8ac5b1d
Initial commit for semantic tokenizer.
gdotdesign Jun 12, 2023
60f1bb5
Simplify semantic tokenizer a bit.
gdotdesign Jun 13, 2023
0e865c6
Working language server implementation.
gdotdesign Jun 13, 2023
1c14a5a
Cleanup semantic tokenizer class.
gdotdesign Jun 13, 2023
ca01ad6
Save keywords automatically instead of manually.
gdotdesign Jun 13, 2023
6926d57
Use an array derived from the actual token types.
gdotdesign Jun 13, 2023
29fb79b
Implement suggestions from code review.
gdotdesign Jun 14, 2023
6b25fc8
Update src/ls/semantic_tokens.cr
gdotdesign Jun 14, 2023
0eea575
Implement HTML highlighting.
gdotdesign Jun 14, 2023
1cd96da
Implement highlight directive.
gdotdesign Jun 14, 2023
529117d
Avoid unnecessary interations.
gdotdesign Jun 14, 2023
79c3f11
Implement suggestions from code review.
gdotdesign Jun 14, 2023
6faec26
Use the ast from the workspace semantic tokens.
gdotdesign Jun 25, 2023
37db9b6
Implementation of localization language structures.
gdotdesign Jun 26, 2023
6e51ae0
Update operation.cr
gdotdesign Jul 18, 2023
673b361
Merge branch 'master' into locales
gdotdesign Jul 18, 2023
92833ca
Update test.
gdotdesign Jul 21, 2023
5e9eef7
Merge branch 'master' into locales
gdotdesign Aug 8, 2023
44ab595
Revert change to the operation formatting.
gdotdesign Aug 8, 2023
a8ecd78
Update Locale.md
gdotdesign Aug 8, 2023
cb99c78
Implement labelled calls.
gdotdesign Jul 21, 2023
dd254f8
Don't reorder arguments in the formatter.
gdotdesign Jul 22, 2023
630c080
Minor fixes.
gdotdesign Jul 26, 2023
d28c7a3
Merge branch 'master' into locales
gdotdesign Sep 6, 2023
095ab66
Merge branch 'locales' into labelled-calls
gdotdesign Sep 6, 2023
d171155
Merge branch 'master' into locales
gdotdesign Sep 7, 2023
88bd4cc
Merge branch 'locales' into labelled-calls
gdotdesign Sep 7, 2023
36c9d98
Apply suggestions from code review
gdotdesign Sep 7, 2023
a2a0c04
Update src/compilers/call.cr
gdotdesign Sep 7, 2023
687550d
Finish renaming an error from code review.
gdotdesign Sep 7, 2023
99a1bac
Merge branch 'master' into labelled-calls
gdotdesign Sep 17, 2023
99acd9f
Merge branch 'master' into labelled-calls
gdotdesign Sep 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions documentation/Language/Locale.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ or if it's a function if can be called:
locale en {
ui: {
buttons: {
ok: (param1 : String, param2 : String) {
"Button #{param1} #{param2}!"
ok: (param1 : String, param2 : String) {
"Button #{param1} #{param2}!"
}
}
}
Expand Down
21 changes: 21 additions & 0 deletions spec/compilers/call_labelled
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
component Main {
fun test (argument1 : String, argument2: Number) : Html {
<div/>
}

fun render : Html {
test(argument2: 0, argument1: "")
}
}
--------------------------------------------------------------------------------
class A extends _C {
a(b, c) {
return _h("div", {});
}

render() {
return this.a(``, 0);
}
};

A.displayName = "Main";
39 changes: 39 additions & 0 deletions spec/type_checking/function_call_labelled
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
component Main {
fun test (argument1 : String, argument2: Number) : Html {
<div/>
}

fun render : Html {
test(argument2: 0, argument1: "")
}
}
---------------------------------------------------------CallWithMixedArguments
component Main {
fun test (argument1 : String, argument2: Number) : Html {
<div/>
}

fun render : Html {
test(0, argument1: "")
}
}
---------------------------------------------------------CallWithMixedArguments
component Main {
fun test (argument1 : String, argument2: Number) : Html {
<div/>
}

fun render : Html {
test(argument2: 0, "")
}
}
-----------------------------------------------------------CallNotFoundArgument
component Main {
fun test (argument1 : String, argument2: Number) : Html {
<div/>
}

fun render : Html {
test(argument3: 0, argument1: "")
}
}
2 changes: 1 addition & 1 deletion src/ast/call.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Mint
class Call < Node
getter arguments, expression

def initialize(@arguments : Array(Expression),
def initialize(@arguments : Array(CallExpression),
@expression : Expression,
@input : Data,
@from : Int32,
Expand Down
14 changes: 14 additions & 0 deletions src/ast/call_expression.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Mint
class Ast
class CallExpression < Node
getter name, expression

def initialize(@expression : Expression,
@name : Variable?,
@input : Data,
@from : Int32,
@to : Int32)
end
end
end
end
12 changes: 10 additions & 2 deletions src/ast/pipe.cr
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,27 @@ module Mint
end

def call
arg =
Ast::CallExpression.new(
expression: argument,
input: argument.input,
from: argument.from,
to: argument.to,
name: nil)

@call ||=
case item = expression
when Ast::Call
Ast::Call.new(
arguments: [argument] + item.arguments,
arguments: [arg] + item.arguments,
expression: item.expression,
input: item.input,
from: item.from,
to: item.to)
else
Ast::Call.new(
expression: expression,
arguments: [argument],
arguments: [arg],
input: input,
from: from,
to: to)
Expand Down
2 changes: 1 addition & 1 deletion src/compiler.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Mint

delegate lookups, checked, cache, component_records, to: @artifacts
delegate ast, types, variables, resolve_order, to: @artifacts
delegate record_field_lookup, locales, to: @artifacts
delegate record_field_lookup, locales, argument_order, to: @artifacts

getter js, style_builder, static_components, static_components_pool
getter build, relative
Expand Down
2 changes: 1 addition & 1 deletion src/compilers/block.cr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module Mint
last =
statements.pop

if statements.empty?
if statements.empty? && !node.async?
if for_function
js.return(last)
else
Expand Down
2 changes: 1 addition & 1 deletion src/compilers/call.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Mint
compile node.expression

arguments =
compile node.arguments, ", "
compile node.arguments.sort_by { |item| argument_order.index(item) || -1 }, ", "

case
when node.expression.is_a?(Ast::InlineFunction)
Expand Down
7 changes: 7 additions & 0 deletions src/compilers/call_expression.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Mint
class Compiler
def _compile(node : Ast::CallExpression)
compile node.expression
end
end
end
14 changes: 14 additions & 0 deletions src/formatters/call_expression.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Mint
class Formatter
def format(node : Ast::CallExpression)
expression =
format node.expression

if name = node.name
"#{name.value}: #{expression}"
else
expression
end
end
end
end
13 changes: 13 additions & 0 deletions src/messages/call_not_found_argument.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
message CallNotFoundArgument do
title "Type Error"

block do
text "I was looking for the argument:"
bold name
text "but it's not there."
end

type_with_text function_type, "The type of the function is:"

snippet node, "The call is here:"
end
9 changes: 9 additions & 0 deletions src/messages/call_with_mixed_arguments.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
message CallWithMixedArguments do
title "Type Error"

block do
text "A call cannot have named and unamed arguments at the same time."
end

snippet node, "It is here:"
end
2 changes: 1 addition & 1 deletion src/parsers/call.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module Mint
arguments = list(
terminator: ')',
separator: ','
) { expression.as(Ast::Expression?) }
) { call_expression.as(Ast::CallExpression?) }
whitespace

char ')', CallExpectedClosingParentheses
Expand Down
27 changes: 27 additions & 0 deletions src/parsers/call_expression.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module Mint
class Parser
def call_expression : Ast::CallExpression?
start do |start_position|
name =
start do
next unless key = variable
whitespace

next unless char! ':'
whitespace

key
end

return unless expression = self.expression

Ast::CallExpression.new(
expression: expression,
from: start_position,
to: position,
input: data,
name: name)
end
end
end
end
2 changes: 1 addition & 1 deletion src/type_checker.cr
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ module Mint

delegate checked, record_field_lookup, component_records, to: artifacts
delegate types, variables, ast, lookups, cache, to: artifacts
delegate assets, resolve_order, locales, to: artifacts
delegate assets, resolve_order, locales, argument_order, to: artifacts

delegate component?, component, stateful?, current_top_level_entity?, to: scope
delegate format, to: formatter
Expand Down
2 changes: 2 additions & 0 deletions src/type_checker/artifacts.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module Mint
class Artifacts
getter ast, lookups, cache, checked, record_field_lookup, assets
getter types, variables, component_records, resolve_order, locales
getter argument_order

def initialize(@ast : Ast,
@component_records = {} of Ast::Component => Record,
Expand All @@ -13,6 +14,7 @@ module Mint
@types = {} of Ast::Node => Checkable,
@cache = {} of Ast::Node => Checkable,
@locales = {} of String => Hash(String, Ast::Node),
@argument_order = [] of Ast::Node,
@resolve_order = [] of Ast::Node,
@checked = Set(Ast::Node).new)
end
Expand Down
10 changes: 5 additions & 5 deletions src/type_checker/comparer.cr
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module Mint
parameters =
node.parameters.map { |param| fill(param, mapping).as(Checkable) }

Type.new(node.name, parameters)
Type.new(node.name, parameters, node.label)
else
node
end
Expand Down Expand Up @@ -113,7 +113,7 @@ module Mint
end

def fresh(node : Variable)
Variable.new(node.name)
Variable.new(node.name, node.label)
end

def fresh(node : Type, mapping = {} of Int32 => Variable)
Expand All @@ -131,7 +131,7 @@ module Mint
end
end

Type.new(node.name, params)
Type.new(node.name, params, node.label)
end

def fresh(node : PartialRecord)
Expand All @@ -142,7 +142,7 @@ module Mint
memo[key] = fresh value
end

PartialRecord.new(node.name, fields)
PartialRecord.new(node.name, fields, label: node.label)
end

def fresh(node : Record)
Expand All @@ -153,7 +153,7 @@ module Mint
memo[key] = fresh value
end

Record.new(node.name, fields)
Record.new(node.name, fields, label: node.label)
end

def prune(node : Variable)
Expand Down
5 changes: 4 additions & 1 deletion src/type_checker/record.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ module Mint
class TypeChecker
class Record
property parameters = [] of Checkable
property label : String?

getter name, fields, mappings

def initialize(
@name : String,
@fields = {} of String => Checkable,
@mappings = {} of String => String?
@mappings = {} of String => String?,
@label = nil
)
end

Expand Down
14 changes: 12 additions & 2 deletions src/type_checker/type.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ module Mint
getter name : String

property optional_count : Int32 = 0
property label : String?

def initialize(@name, @parameters = [] of Checkable)
def initialize(@name, @parameters = [] of Checkable, @label = nil)
end

def to_mint
Expand All @@ -18,7 +19,16 @@ module Mint
name
else
params =
parameters.map(&.to_pretty.as(String))
parameters.map do |param|
pretty =
param.to_pretty.as(String)

if param.label
"#{param.label}: #{pretty}"
else
pretty
end
end
Comment on lines -21 to +31
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd refactor this into Record#to_pretty(named_arguments: true).


if params.size > 1 || params[0].includes?("\n")
"#{name}(\n#{params.join(",\n").indent})"
Expand Down
4 changes: 3 additions & 1 deletion src/type_checker/variable.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ module Mint

property parameters = [] of Checkable
property instance : Checkable?
property label : String?

getter name : String
getter id : Int32

def initialize(@name)
def initialize(@name, @label = nil)
@id = (@@id += 1)
end

Expand Down
1 change: 1 addition & 0 deletions src/type_checkers/argument.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module Mint
node.default.try { |default| resolve default }

resolve_type(resolve(node.type))
.tap(&.label = node.name.try(&.value))
end
end
end
Loading