55 FunctionCallNode ,
66 MolangData ,
77 MolangFunction ,
8+ MolangParameter ,
89 MolangSet ,
910 MolangSyntaxError ,
1011 NodeType ,
@@ -233,6 +234,34 @@ export function diagnose_molang_function(fn: FunctionCallNode, diagnoser: Diagno
233234 'molang.function.arguments' ,
234235 ) ;
235236 }
237+
238+ // Validate parameter types
239+ for ( let i = 0 ; i < fn . arguments . length ; i ++ ) {
240+ const arg = fn . arguments [ i ] ;
241+ let expectedParam : MolangParameter | undefined ;
242+
243+ // Determine which parameter definition to use
244+ if ( i < fnData . parameters . length ) {
245+ // Use the fixed parameter definition
246+ expectedParam = fnData . parameters [ i ] ;
247+ } else if ( fnData . repeatableParam ) {
248+ // Use the repeatable parameter definition for additional args
249+ expectedParam = fnData . repeatableParam ;
250+ }
251+
252+ // Validate type if specified
253+ if ( expectedParam ?. type ) {
254+ const actualType = getArgumentType ( arg ) ;
255+ if ( actualType && actualType !== expectedParam . type ) {
256+ diagnoser . add (
257+ OffsetWord . create ( `${ fn . scope } .${ fn . names . join ( '.' ) } ` , fn . position ) ,
258+ `wrong argument type at position ${ i + 1 } , expected ${ expectedParam . type } but got ${ actualType } ` ,
259+ DiagnosticSeverity . error ,
260+ 'molang.function.arguments.type' ,
261+ ) ;
262+ }
263+ }
264+ }
236265 } else {
237266 // Check for exact parameter count
238267 if ( fnData . parameters . length != fn . arguments . length ) {
@@ -242,7 +271,45 @@ export function diagnose_molang_function(fn: FunctionCallNode, diagnoser: Diagno
242271 DiagnosticSeverity . error ,
243272 'molang.function.arguments' ,
244273 ) ;
274+ } else {
275+ // Validate parameter types for exact match case
276+ for ( let i = 0 ; i < fn . arguments . length ; i ++ ) {
277+ const arg = fn . arguments [ i ] ;
278+ const expectedParam = fnData . parameters [ i ] ;
279+
280+ if ( expectedParam ?. type ) {
281+ const actualType = getArgumentType ( arg ) ;
282+ if ( actualType && actualType !== expectedParam . type ) {
283+ diagnoser . add (
284+ OffsetWord . create ( `${ fn . scope } .${ fn . names . join ( '.' ) } ` , fn . position ) ,
285+ `wrong argument type at position ${ i + 1 } , expected ${ expectedParam . type } but got ${ actualType } ` ,
286+ DiagnosticSeverity . error ,
287+ 'molang.function.arguments.type' ,
288+ ) ;
289+ }
290+ }
291+ }
245292 }
246293 }
247294 }
248295}
296+
297+ /**
298+ * Helper function to determine the type of an argument node
299+ */
300+ function getArgumentType ( arg : ExpressionNode ) : 'string' | 'float' | 'boolean' | undefined {
301+ switch ( arg . type ) {
302+ case NodeType . StringLiteral :
303+ return 'string' ;
304+ case NodeType . Literal :
305+ // Check if it's a boolean literal (true/false) or numeric
306+ const value = ( arg as any ) . value ?. toLowerCase ( ) ;
307+ if ( value === 'true' || value === 'false' ) {
308+ return 'boolean' ;
309+ }
310+ return 'float' ;
311+ default :
312+ // For complex expressions, we can't determine the type statically
313+ return undefined ;
314+ }
315+ }
0 commit comments