@@ -22,28 +22,28 @@ var fn = AST.extends(function(parent, node) {
2222fn . prototype . checkArgumentType = function ( nullable , name , type , indent , errTrigger ) {
2323 var checks = [ ] ;
2424 if ( nullable ) {
25- checks . push ( indent + 'if(' + name + ' != null) {\n' ) ;
25+ checks . push ( indent + 'if (' + name + ' != null) {\n' ) ;
2626 indent += ' ' ;
2727 }
2828 if ( type === 'self' ) {
29- checks . push ( indent + 'if(!(' + name + ' instanceof this))' + errTrigger ) ;
29+ checks . push ( indent + 'if (!(' + name + ' instanceof this))' + errTrigger ) ;
3030 } else if ( type === 'array' ) {
31- checks . push ( indent + 'if(!Array.isArray(' + name + '))' + errTrigger ) ;
31+ checks . push ( indent + 'if (!Array.isArray(' + name + '))' + errTrigger ) ;
3232 } else if ( type === 'callable' ) {
3333 // @fixme arrays / strings can also be valid callable
3434 // http://php.net/manual/en/language.types.callable.php
35- checks . push ( indent + 'if(typeof ' + name + ' !== \'function\')' + errTrigger ) ;
35+ checks . push ( indent + 'if (typeof ' + name + ' !== \'function\')' + errTrigger ) ;
3636 } else if ( type === 'bool' ) {
37- checks . push ( indent + 'if(typeof ' + name + ' !== \'boolean\' && !(' + name + ' instanceof Boolean))' + errTrigger ) ;
37+ checks . push ( indent + 'if (typeof ' + name + ' !== \'boolean\' && !(' + name + ' instanceof Boolean))' + errTrigger ) ;
3838 } else if ( type === 'float' ) {
39- checks . push ( indent + 'if(typeof ' + name + ' !== \'number\' || ' + name + ' % 1 === 0)' + errTrigger ) ;
39+ checks . push ( indent + 'if (typeof ' + name + ' !== \'number\' || ' + name + ' % 1 === 0)' + errTrigger ) ;
4040 } else if ( type === 'int' ) {
41- checks . push ( indent + 'if(typeof ' + name + ' !== \'number\' || ' + name + ' % 1 !== 0)' + errTrigger ) ;
41+ checks . push ( indent + 'if (typeof ' + name + ' !== \'number\' || ' + name + ' % 1 !== 0)' + errTrigger ) ;
4242 } else if ( type === 'string' ) {
43- checks . push ( indent + 'if(typeof ' + name + ' !== \'string\' && !(' + name + ' instanceof String))' + errTrigger ) ;
43+ checks . push ( indent + 'if (typeof ' + name + ' !== \'string\' && !(' + name + ' instanceof String))' + errTrigger ) ;
4444 } else {
4545 // check the class
46- checks . push ( indent + 'if(!' + name + '.is(\'' + type + '\'))' + errTrigger ) ;
46+ checks . push ( indent + 'if (!' + name + '.is(\'' + type + '\'))' + errTrigger ) ;
4747 }
4848 if ( nullable ) {
4949 indent = indent . substring ( 0 , indent . length - 2 ) ;
@@ -68,15 +68,19 @@ fn.prototype.toString = function (indent) {
6868
6969 // arguments
7070 var parameters = [ ] ;
71- var checks = [ ] ;
71+ var typeChecks = [ ] ;
72+ var defaultChecks = [ ] ;
73+ var argsReflection = [ ] ;
7274 indent += ' ' ;
7375
7476 for ( var i = 0 ; i < this . node . arguments . length ; i ++ ) {
7577 var arg = this . node . arguments [ i ] ;
7678 parameters . push ( arg . name ) ;
79+ var argItem = { name : arg . name } ;
7780 if ( ! arg . variadic ) {
7881 if ( arg . type ) {
79- checks = checks . concat (
82+ argItem . type = arg . type ;
83+ typeChecks = typeChecks . concat (
8084 this . checkArgumentType (
8185 arg . nullable || (
8286 arg . value && arg . value . kind === 'constref' &&
@@ -91,18 +95,19 @@ fn.prototype.toString = function (indent) {
9195 ) ;
9296 }
9397 if ( arg . value ) {
98+ argItem . default = arg . value ;
9499 // @todo sets a default value if not defined
95- checks . push ( indent + 'if (typeof ' + arg . name + ' === \'undefined\') ' + arg . name + ' = null;\n' ) ;
100+ defaultChecks . push ( indent + 'if (typeof ' + arg . name + ' === \'undefined\') ' + arg . name + ' = null;\n' ) ;
96101 }
97102 } else {
98103 // handle variadic arguments
99- checks . push (
104+ defaultChecks . push (
100105 indent + arg . name + ' = Array.prototype.slice.call(arguments, ' + i + ');'
101106 ) ;
102107 if ( arg . type ) {
103108 // check each variadic argument
104- checks . push ( indent + 'for(var $i = 0; $i < ' + arg . name + '.length; $i++) {\n' ) ;
105- checks = checks . concat (
109+ typeChecks . push ( indent + 'for(var $i = 0; $i < ' + arg . name + '.length; $i++) {\n' ) ;
110+ typeChecks = typeChecks . concat (
106111 this . checkArgumentType (
107112 arg . nullable || (
108113 arg . value && arg . value . kind === 'constref' &&
@@ -115,39 +120,53 @@ fn.prototype.toString = function (indent) {
115120 ' $php.type_error(' + i + ', \'' + arg . name + '\', \'' + name + '\', \'' + arg . type + '\', ' + arg . name + ');'
116121 )
117122 ) ;
118- checks . push ( indent + '}' ) ;
123+ typeChecks . push ( indent + '}' ) ;
119124 }
120125 }
126+ argsReflection . push ( argItem ) ;
121127 }
122128
123129 // function body
124130 buffer += parameters . join ( ', ' ) + ') {\n' ;
125- if ( checks . length > 0 ) {
126- buffer += checks . join ( '\n' ) + '\n' ;
131+ if ( defaultChecks . length > 0 ) {
132+ buffer += defaultChecks . join ( '\n' ) + '\n' ;
133+ }
134+ if ( typeChecks . length > 0 ) {
135+ buffer += indent + 'if ($php.context.strictTypes) {\n' ;
136+ buffer += ' ' + typeChecks . join ( '\n ' ) + '\n' ;
137+ buffer += indent + '}\n' ;
127138 }
128139 buffer += this . variablesToString ( indent ) ;
140+ var returnType = 'null' ;
129141 if ( this . node . type ) {
130- buffer += indent + 'var $result = (function() {\n' ;
142+ returnType = '\'' + this . node . type + '\'' ;
143+ buffer += indent + 'var $result;\n' ;
144+ buffer += indent + 'do {\n' ;
131145 buffer += AST . prototype . toString . apply ( this , [ indent + ' ' ] ) ;
132- buffer += indent + '})();\n' ;
133- buffer += this . checkArgumentType (
146+ buffer += indent + '} while(false);\n' ;
147+ buffer += indent + 'if ($php.context.strictTypes) {\n' ;
148+ buffer += ' ' + this . checkArgumentType (
134149 this . node . nullable ,
135150 '$result' ,
136151 this . node . type ,
137152 indent ,
138153 ' $php.type_error(-1, null, \'' + name + '\', \'' + this . node . type + '\', $result);'
139- ) . join ( '\n' ) ;
140- buffer += '\n' + indent + 'return $result;\n' ;
154+ ) . join ( '\n ' ) + '\n' + indent + '}\n' ;
141155 } else {
142156 buffer += AST . prototype . toString . apply ( this , [ indent ] ) ;
143157 }
158+ buffer += indent + 'return $result;\n' ;
144159 indent = indent . substring ( 0 , indent . length - 2 ) ;
145160 buffer += indent + '}' ;
146161
147162 // encapsulate
148163 if ( this . node . kind === 'function' ) {
149164 // global function
150- buffer = indent + '$php.context.function.declare(\'' + this . node . name + '\', ' + buffer + ');\n'
165+ var body = buffer ;
166+ buffer = indent + '$php.context.function.declare(\n' ;
167+ buffer += indent + ' \'' + this . node . name + '\',\n' ;
168+ buffer += indent + ' ' + JSON . stringify ( argsReflection ) + ',\n' ;
169+ buffer += indent + ' ' + returnType + ', ' + body + ');\n' ;
151170 } else if ( this . node . kind === 'method' ) {
152171 // @todo method declaration
153172 } else if ( ! ( this . _parent instanceof Statement ) ) {
0 commit comments