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 ::BracketAccess ) : Checkable
23+ index, expression =
24+ node.index, node.expression
25+
26+ type =
27+ resolve expression
28+
29+ index_type =
30+ resolve index
31+
32+ if type .name == " Tuple"
33+ case index
34+ when Ast ::NumberLiteral
35+ error! :bracket_access_invalid_tuple_index do
36+ block " The index of an array access for a tuple is a float, " \
37+ " it can be only integer."
38+ snippet " The access:" , node
39+ end if index.float?
40+
41+ parameter =
42+ type .parameters[index.value.to_i]?
43+
44+ error! :bracket_access_invalid_tuple do
45+ snippet " The tuple has only #{ type .parameters.size} members, but " \
46+ " you wanted to access the #{ ordinal(index.value.to_i + 1 ) } " \
47+ " . The exact type of the tuple is:" , type
48+ snippet " The tuple:" , expression
49+ end unless parameter
50+
51+ parameter
52+ else
53+ error! :bracket_access_invalid_tuple_access do
54+ snippet " Tuples do not support non integer access:" , index
55+ snippet " The tuple:" , expression
56+ end
57+ end
58+ elsif type .name == " Map" && type .parameters.size == 2
59+ error! :bracket_access_index_not_map_key do
60+ block " The type of the index of a bracket access does not match the type of the keys."
61+ expected type .parameters.first, type .parameters.first
62+ snippet " The index:" , index
63+ end unless Comparer .compare(type .parameters.first, index_type)
64+
65+ Type .new(" Maybe" , [type .parameters.last] of Checkable )
66+ elsif type .name == " Array" && type .parameters.size == 1
67+ error! :bracket_access_index_not_number do
68+ block " The type of the index of a bracket access is not a number."
69+ expected NUMBER , index_type
70+ snippet " The index:" , index
71+ end unless Comparer .compare(index_type, NUMBER )
72+
73+ Type .new(" Maybe" , [type .parameters.first] of Checkable )
74+ else
75+ error! :bracket_access_not_accessible do
76+ block " The entity you are trying to access an item from is not an " \
77+ " array, map or a tuple."
78+ expected " Array(a), Map(a, b) or Tuple(...)" , type
79+ snippet " The array:" , expression
80+ end
81+ end
82+ end
83+ end
84+ end
0 commit comments