1+ # -----------------------------------------------------------------------
2+ # This file is part of MoonScript
3+ #
4+ # MoonSript is free software: you can redistribute it and/or modify
5+ # it under the terms of the GNU General Public License as published by
6+ # the Free Software Foundation, either version 3 of the License, or
7+ # (at your option) any later version.
8+ #
9+ # MoonSript is distributed in the hope that it will be useful,
10+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+ # GNU General Public License for more details.
13+ #
14+ # You should have received a copy of the GNU General Public License
15+ # along with MoonSript. If not, see <https://www.gnu.org/licenses/>.
16+ #
17+ # Copyright (C) 2025 Krisna Pranav, MoonScript Developers
18+ # -----------------------------------------------------------------------
19+
20+ module MoonScript
21+ class TypeChecker
22+ def check (node : Ast ::Block ) : Checkable
23+ if node.expressions.all?(Ast ::CssDefinition )
24+ resolve node.expressions
25+ VOID
26+ else
27+ expressions =
28+ node.expressions.select(Ast ::Statement )
29+
30+ error! :block_no_expressions do
31+ block " This block doesn't have any statements. It should have at least one."
32+ snippet node
33+ end if expressions.empty?
34+
35+ expressions.dup.tap do |items |
36+ variables = [] of VariableScope
37+
38+ while item = items.shift?
39+ variables.each do |var |
40+ scope.add(node, var[0 ], var[2 ])
41+ end
42+
43+ # This is to allow recursion
44+ case target = item.target
45+ when Ast ::Variable
46+ case value = item.expression
47+ when Ast ::InlineFunction
48+ cache[target] =
49+ static_type_signature(value)
50+
51+ scope.add(item, target.value, target)
52+ end
53+ end
54+
55+ type = resolve item
56+ variables = destructure(item.target, type )
57+ end
58+ end
59+
60+ last =
61+ cache[expressions.last]
62+
63+ error! :statement_last_target do
64+ block do
65+ text " The"
66+ bold " last statement"
67+ text " of a block cannot be an"
68+ bold " assignment:"
69+ end
70+
71+ snippet node
72+ end if expressions.last.target
73+
74+ node.expressions.select(Ast ::Statement ).each do |item |
75+ next unless return_value = item.return_value
76+
77+ type =
78+ cache[return_value]
79+
80+ error! :statement_return_type_mismatch do
81+ snippet " The type of a return call does not match the return " \
82+ " block:" , type
83+
84+ snippet " I was expecting:" , last
85+ snippet " It return call in question is here:" , return_value
86+ snippet " The value of block:" , expressions.last
87+ end unless Comparer .compare(last, type )
88+ end
89+
90+ if async.includes?(node) && last.name != " Promise"
91+ Type .new(" Promise" , [last] of Checkable )
92+ else
93+ last
94+ end
95+ end
96+ end
97+ end
98+ end
0 commit comments