Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
godot
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
community
godot
Commits
425ec691
Unverified
Commit
425ec691
authored
Mar 04, 2019
by
Rémi Verschelde
Committed by
GitHub
Mar 04, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Forbid implicit type conversion in GDScript"
parent
49d82f24
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
110 additions
and
16 deletions
+110
-16
gdscript_function.cpp
modules/gdscript/gdscript_function.cpp
+8
-3
gdscript_function.h
modules/gdscript/gdscript_function.h
+6
-2
gdscript_parser.cpp
modules/gdscript/gdscript_parser.cpp
+95
-10
gdscript_parser.h
modules/gdscript/gdscript_parser.h
+1
-1
No files found.
modules/gdscript/gdscript_function.cpp
View file @
425ec691
...
@@ -328,8 +328,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
...
@@ -328,8 +328,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
continue
;
continue
;
}
}
if
(
!
argument_types
[
i
].
is_type
(
*
p_args
[
i
]))
{
if
(
!
argument_types
[
i
].
is_type
(
*
p_args
[
i
]
,
true
))
{
if
(
argument_types
[
i
].
is_type
(
Variant
()))
{
if
(
argument_types
[
i
].
is_type
(
Variant
()
,
true
))
{
memnew_placement
(
&
stack
[
i
],
Variant
);
memnew_placement
(
&
stack
[
i
],
Variant
);
continue
;
continue
;
}
else
{
}
else
{
...
@@ -339,7 +339,12 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
...
@@ -339,7 +339,12 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
return
Variant
();
return
Variant
();
}
}
}
}
memnew_placement
(
&
stack
[
i
],
Variant
(
*
p_args
[
i
]));
if
(
argument_types
[
i
].
kind
==
GDScriptDataType
::
BUILTIN
)
{
Variant
arg
=
Variant
::
construct
(
argument_types
[
i
].
builtin_type
,
&
p_args
[
i
],
1
,
r_err
);
memnew_placement
(
&
stack
[
i
],
Variant
(
arg
));
}
else
{
memnew_placement
(
&
stack
[
i
],
Variant
(
*
p_args
[
i
]));
}
}
}
for
(
int
i
=
p_argcount
;
i
<
_stack_size
;
i
++
)
{
for
(
int
i
=
p_argcount
;
i
<
_stack_size
;
i
++
)
{
memnew_placement
(
&
stack
[
i
],
Variant
);
memnew_placement
(
&
stack
[
i
],
Variant
);
...
...
modules/gdscript/gdscript_function.h
View file @
425ec691
...
@@ -55,7 +55,7 @@ struct GDScriptDataType {
...
@@ -55,7 +55,7 @@ struct GDScriptDataType {
StringName
native_type
;
StringName
native_type
;
Ref
<
Script
>
script_type
;
Ref
<
Script
>
script_type
;
bool
is_type
(
const
Variant
&
p_variant
)
const
{
bool
is_type
(
const
Variant
&
p_variant
,
bool
p_allow_implicit_conversion
=
false
)
const
{
if
(
!
has_type
)
return
true
;
// Can't type check
if
(
!
has_type
)
return
true
;
// Can't type check
switch
(
kind
)
{
switch
(
kind
)
{
...
@@ -63,7 +63,11 @@ struct GDScriptDataType {
...
@@ -63,7 +63,11 @@ struct GDScriptDataType {
break
;
break
;
case
BUILTIN
:
{
case
BUILTIN
:
{
Variant
::
Type
var_type
=
p_variant
.
get_type
();
Variant
::
Type
var_type
=
p_variant
.
get_type
();
return
builtin_type
==
var_type
;
bool
valid
=
builtin_type
==
var_type
;
if
(
!
valid
&&
p_allow_implicit_conversion
)
{
valid
=
Variant
::
can_convert_strict
(
var_type
,
builtin_type
);
}
return
valid
;
}
break
;
}
break
;
case
NATIVE
:
{
case
NATIVE
:
{
if
(
p_variant
.
get_type
()
==
Variant
::
NIL
)
{
if
(
p_variant
.
get_type
()
==
Variant
::
NIL
)
{
...
...
modules/gdscript/gdscript_parser.cpp
View file @
425ec691
...
@@ -5801,7 +5801,7 @@ Variant::Operator GDScriptParser::_get_variant_operation(const OperatorNode::Ope
...
@@ -5801,7 +5801,7 @@ Variant::Operator GDScriptParser::_get_variant_operation(const OperatorNode::Ope
}
}
}
}
bool
GDScriptParser
::
_is_type_compatible
(
const
DataType
&
p_container
,
const
DataType
&
p_expression
)
const
{
bool
GDScriptParser
::
_is_type_compatible
(
const
DataType
&
p_container
,
const
DataType
&
p_expression
,
bool
p_allow_implicit_conversion
)
const
{
// Ignore for completion
// Ignore for completion
if
(
!
check_types
||
for_completion
)
{
if
(
!
check_types
||
for_completion
)
{
return
true
;
return
true
;
...
@@ -5817,6 +5817,9 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data
...
@@ -5817,6 +5817,9 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data
if
(
p_container
.
kind
==
DataType
::
BUILTIN
&&
p_expression
.
kind
==
DataType
::
BUILTIN
)
{
if
(
p_container
.
kind
==
DataType
::
BUILTIN
&&
p_expression
.
kind
==
DataType
::
BUILTIN
)
{
bool
valid
=
p_container
.
builtin_type
==
p_expression
.
builtin_type
;
bool
valid
=
p_container
.
builtin_type
==
p_expression
.
builtin_type
;
if
(
p_allow_implicit_conversion
)
{
valid
=
valid
||
Variant
::
can_convert_strict
(
p_expression
.
builtin_type
,
p_container
.
builtin_type
);
}
return
valid
;
return
valid
;
}
}
...
@@ -6685,7 +6688,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
...
@@ -6685,7 +6688,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
arg_type
.
native_type
=
mi
.
arguments
[
i
].
class_name
;
arg_type
.
native_type
=
mi
.
arguments
[
i
].
class_name
;
}
}
if
(
!
_is_type_compatible
(
arg_type
,
par_types
[
i
]))
{
if
(
!
_is_type_compatible
(
arg_type
,
par_types
[
i
]
,
true
))
{
types_match
=
false
;
types_match
=
false
;
break
;
break
;
}
else
{
}
else
{
...
@@ -6927,7 +6930,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
...
@@ -6927,7 +6930,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
if
(
par_type
.
may_yield
&&
p_call
->
arguments
[
i
]
->
type
==
Node
::
TYPE_OPERATOR
)
{
if
(
par_type
.
may_yield
&&
p_call
->
arguments
[
i
]
->
type
==
Node
::
TYPE_OPERATOR
)
{
_add_warning
(
GDScriptWarning
::
FUNCTION_MAY_YIELD
,
p_call
->
line
,
_find_function_name
(
static_cast
<
OperatorNode
*>
(
p_call
->
arguments
[
i
])));
_add_warning
(
GDScriptWarning
::
FUNCTION_MAY_YIELD
,
p_call
->
line
,
_find_function_name
(
static_cast
<
OperatorNode
*>
(
p_call
->
arguments
[
i
])));
}
}
}
else
if
(
!
_is_type_compatible
(
arg_types
[
i
-
arg_diff
],
par_type
))
{
}
else
if
(
!
_is_type_compatible
(
arg_types
[
i
-
arg_diff
],
par_type
,
true
))
{
// Supertypes are acceptable for dynamic compliance
// Supertypes are acceptable for dynamic compliance
if
(
!
_is_type_compatible
(
par_type
,
arg_types
[
i
-
arg_diff
]))
{
if
(
!
_is_type_compatible
(
par_type
,
arg_types
[
i
-
arg_diff
]))
{
_set_error
(
"At '"
+
callee_name
+
"()' call, argument "
+
itos
(
i
-
arg_diff
+
1
)
+
". Assigned type ("
+
_set_error
(
"At '"
+
callee_name
+
"()' call, argument "
+
itos
(
i
-
arg_diff
+
1
)
+
". Assigned type ("
+
...
@@ -7390,6 +7393,33 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
...
@@ -7390,6 +7393,33 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
// Try supertype test
// Try supertype test
if
(
_is_type_compatible
(
expr_type
,
v
.
data_type
))
{
if
(
_is_type_compatible
(
expr_type
,
v
.
data_type
))
{
_mark_line_as_unsafe
(
v
.
line
);
_mark_line_as_unsafe
(
v
.
line
);
}
else
{
// Try with implicit conversion
if
(
v
.
data_type
.
kind
!=
DataType
::
BUILTIN
||
!
_is_type_compatible
(
v
.
data_type
,
expr_type
,
true
))
{
_set_error
(
"Assigned expression type ("
+
expr_type
.
to_string
()
+
") doesn't match the variable's type ("
+
v
.
data_type
.
to_string
()
+
")."
,
v
.
line
);
return
;
}
// Replace assignment with implict conversion
BuiltInFunctionNode
*
convert
=
alloc_node
<
BuiltInFunctionNode
>
();
convert
->
line
=
v
.
line
;
convert
->
function
=
GDScriptFunctions
::
TYPE_CONVERT
;
ConstantNode
*
tgt_type
=
alloc_node
<
ConstantNode
>
();
tgt_type
->
line
=
v
.
line
;
tgt_type
->
value
=
(
int
)
v
.
data_type
.
builtin_type
;
OperatorNode
*
convert_call
=
alloc_node
<
OperatorNode
>
();
convert_call
->
line
=
v
.
line
;
convert_call
->
op
=
OperatorNode
::
OP_CALL
;
convert_call
->
arguments
.
push_back
(
convert
);
convert_call
->
arguments
.
push_back
(
v
.
expression
);
convert_call
->
arguments
.
push_back
(
tgt_type
);
v
.
expression
=
convert_call
;
v
.
initial_assignment
->
arguments
.
write
[
1
]
=
convert_call
;
}
}
}
}
...
@@ -7430,7 +7460,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
...
@@ -7430,7 +7460,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
// Check export hint
// Check export hint
if
(
v
.
data_type
.
has_type
&&
v
.
_export
.
type
!=
Variant
::
NIL
)
{
if
(
v
.
data_type
.
has_type
&&
v
.
_export
.
type
!=
Variant
::
NIL
)
{
DataType
export_type
=
_type_from_property
(
v
.
_export
);
DataType
export_type
=
_type_from_property
(
v
.
_export
);
if
(
!
_is_type_compatible
(
v
.
data_type
,
export_type
))
{
if
(
!
_is_type_compatible
(
v
.
data_type
,
export_type
,
true
))
{
_set_error
(
"Export hint type ("
+
export_type
.
to_string
()
+
") doesn't match the variable's type ("
+
_set_error
(
"Export hint type ("
+
export_type
.
to_string
()
+
") doesn't match the variable's type ("
+
v
.
data_type
.
to_string
()
+
")."
,
v
.
data_type
.
to_string
()
+
")."
,
v
.
line
);
v
.
line
);
...
@@ -7551,7 +7581,7 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) {
...
@@ -7551,7 +7581,7 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) {
}
else
{
}
else
{
p_function
->
return_type
=
_resolve_type
(
p_function
->
return_type
,
p_function
->
line
);
p_function
->
return_type
=
_resolve_type
(
p_function
->
return_type
,
p_function
->
line
);
if
(
!
_is_type_compatible
(
p_function
->
argument_types
[
i
],
def_type
))
{
if
(
!
_is_type_compatible
(
p_function
->
argument_types
[
i
],
def_type
,
true
))
{
String
arg_name
=
p_function
->
arguments
[
i
];
String
arg_name
=
p_function
->
arguments
[
i
];
_set_error
(
"Value type ("
+
def_type
.
to_string
()
+
") doesn't match the type of argument '"
+
_set_error
(
"Value type ("
+
def_type
.
to_string
()
+
") doesn't match the type of argument '"
+
arg_name
+
"' ("
+
p_function
->
arguments
[
i
]
+
")"
,
arg_name
+
"' ("
+
p_function
->
arguments
[
i
]
+
")"
,
...
@@ -7739,13 +7769,41 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
...
@@ -7739,13 +7769,41 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
}
}
#endif // DEBUG_ENABLED
#endif // DEBUG_ENABLED
if
(
check_types
&&
!
_is_type_compatible
(
lv
->
datatype
,
assign_type
))
{
if
(
!
_is_type_compatible
(
lv
->
datatype
,
assign_type
))
{
// Try supertype test
// Try supertype test
if
(
_is_type_compatible
(
assign_type
,
lv
->
datatype
))
{
if
(
_is_type_compatible
(
assign_type
,
lv
->
datatype
))
{
_mark_line_as_unsafe
(
lv
->
line
);
_mark_line_as_unsafe
(
lv
->
line
);
}
else
{
}
else
{
_set_error
(
"Assigned value type ("
+
assign_type
.
to_string
()
+
") does not match variable type ("
+
lv
->
datatype
.
to_string
()
+
")"
,
lv
->
line
);
// Try implict conversion
return
;
if
(
lv
->
datatype
.
kind
!=
DataType
::
BUILTIN
||
!
_is_type_compatible
(
lv
->
datatype
,
assign_type
,
true
))
{
_set_error
(
"Assigned value type ("
+
assign_type
.
to_string
()
+
") doesn't match the variable's type ("
+
lv
->
datatype
.
to_string
()
+
")."
,
lv
->
line
);
return
;
}
// Replace assignment with implict conversion
BuiltInFunctionNode
*
convert
=
alloc_node
<
BuiltInFunctionNode
>
();
convert
->
line
=
lv
->
line
;
convert
->
function
=
GDScriptFunctions
::
TYPE_CONVERT
;
ConstantNode
*
tgt_type
=
alloc_node
<
ConstantNode
>
();
tgt_type
->
line
=
lv
->
line
;
tgt_type
->
value
=
(
int
)
lv
->
datatype
.
builtin_type
;
OperatorNode
*
convert_call
=
alloc_node
<
OperatorNode
>
();
convert_call
->
line
=
lv
->
line
;
convert_call
->
op
=
OperatorNode
::
OP_CALL
;
convert_call
->
arguments
.
push_back
(
convert
);
convert_call
->
arguments
.
push_back
(
lv
->
assign
);
convert_call
->
arguments
.
push_back
(
tgt_type
);
lv
->
assign
=
convert_call
;
lv
->
assign_op
->
arguments
.
write
[
1
]
=
convert_call
;
#ifdef DEBUG_ENABLED
if
(
lv
->
datatype
.
builtin_type
==
Variant
::
INT
&&
assign_type
.
builtin_type
==
Variant
::
REAL
)
{
_add_warning
(
GDScriptWarning
::
NARROWING_CONVERSION
,
lv
->
line
);
}
#endif // DEBUG_ENABLED
}
}
}
}
if
(
lv
->
datatype
.
infer_type
)
{
if
(
lv
->
datatype
.
infer_type
)
{
...
@@ -7847,8 +7905,35 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
...
@@ -7847,8 +7905,35 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
if
(
_is_type_compatible
(
rh_type
,
lh_type
))
{
if
(
_is_type_compatible
(
rh_type
,
lh_type
))
{
_mark_line_as_unsafe
(
op
->
line
);
_mark_line_as_unsafe
(
op
->
line
);
}
else
{
}
else
{
_set_error
(
"Assigned value type ("
+
rh_type
.
to_string
()
+
") does not match variable type ("
+
lh_type
.
to_string
()
+
")"
,
op
->
line
);
// Try implict conversion
return
;
if
(
lh_type
.
kind
!=
DataType
::
BUILTIN
||
!
_is_type_compatible
(
lh_type
,
rh_type
,
true
))
{
_set_error
(
"Assigned value type ("
+
rh_type
.
to_string
()
+
") doesn't match the variable's type ("
+
lh_type
.
to_string
()
+
")."
,
op
->
line
);
return
;
}
// Replace assignment with implict conversion
BuiltInFunctionNode
*
convert
=
alloc_node
<
BuiltInFunctionNode
>
();
convert
->
line
=
op
->
line
;
convert
->
function
=
GDScriptFunctions
::
TYPE_CONVERT
;
ConstantNode
*
tgt_type
=
alloc_node
<
ConstantNode
>
();
tgt_type
->
line
=
op
->
line
;
tgt_type
->
value
=
(
int
)
lh_type
.
builtin_type
;
OperatorNode
*
convert_call
=
alloc_node
<
OperatorNode
>
();
convert_call
->
line
=
op
->
line
;
convert_call
->
op
=
OperatorNode
::
OP_CALL
;
convert_call
->
arguments
.
push_back
(
convert
);
convert_call
->
arguments
.
push_back
(
op
->
arguments
[
1
]);
convert_call
->
arguments
.
push_back
(
tgt_type
);
op
->
arguments
.
write
[
1
]
=
convert_call
;
#ifdef DEBUG_ENABLED
if
(
lh_type
.
builtin_type
==
Variant
::
INT
&&
rh_type
.
builtin_type
==
Variant
::
REAL
)
{
_add_warning
(
GDScriptWarning
::
NARROWING_CONVERSION
,
op
->
line
);
}
#endif // DEBUG_ENABLED
}
}
}
}
#ifdef DEBUG_ENABLED
#ifdef DEBUG_ENABLED
...
...
modules/gdscript/gdscript_parser.h
View file @
425ec691
...
@@ -607,7 +607,7 @@ private:
...
@@ -607,7 +607,7 @@ private:
Variant
::
Operator
_get_variant_operation
(
const
OperatorNode
::
Operator
&
p_op
)
const
;
Variant
::
Operator
_get_variant_operation
(
const
OperatorNode
::
Operator
&
p_op
)
const
;
bool
_get_function_signature
(
DataType
&
p_base_type
,
const
StringName
&
p_function
,
DataType
&
r_return_type
,
List
<
DataType
>
&
r_arg_types
,
int
&
r_default_arg_count
,
bool
&
r_static
,
bool
&
r_vararg
)
const
;
bool
_get_function_signature
(
DataType
&
p_base_type
,
const
StringName
&
p_function
,
DataType
&
r_return_type
,
List
<
DataType
>
&
r_arg_types
,
int
&
r_default_arg_count
,
bool
&
r_static
,
bool
&
r_vararg
)
const
;
bool
_get_member_type
(
const
DataType
&
p_base_type
,
const
StringName
&
p_member
,
DataType
&
r_member_type
)
const
;
bool
_get_member_type
(
const
DataType
&
p_base_type
,
const
StringName
&
p_member
,
DataType
&
r_member_type
)
const
;
bool
_is_type_compatible
(
const
DataType
&
p_container
,
const
DataType
&
p_expression
)
const
;
bool
_is_type_compatible
(
const
DataType
&
p_container
,
const
DataType
&
p_expression
,
bool
p_allow_implicit_conversion
=
false
)
const
;
DataType
_reduce_node_type
(
Node
*
p_node
);
DataType
_reduce_node_type
(
Node
*
p_node
);
DataType
_reduce_function_call_type
(
const
OperatorNode
*
p_call
);
DataType
_reduce_function_call_type
(
const
OperatorNode
*
p_call
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment