@@ -65,7 +65,8 @@ import {
65
65
ResConOverloadInstr ,
66
66
ResOverrideInstr ,
67
67
ResTypeContInstr ,
68
- StructType
68
+ StructType ,
69
+ NativeDeclaration
69
70
} from './types'
70
71
import {
71
72
defaultValues ,
@@ -87,15 +88,15 @@ import {
87
88
searchMainMtdClass ,
88
89
prependExpConInvIfNeeded ,
89
90
isStatic ,
90
- isNative ,
91
+ isNativeMethodDeclaration ,
91
92
resOverload ,
92
93
resOverride ,
93
94
resConOverload ,
94
95
isNull ,
95
96
makeNonLocalVarNonParamSimpleNameQualified ,
96
97
getFullyQualifiedDescriptor
97
98
} from './utils'
98
- import { natives } from './natives'
99
+ import { foreigns } from './natives'
99
100
100
101
type CmdEvaluator = (
101
102
command : ControlItem ,
@@ -253,9 +254,31 @@ export const cmdEvaluators: { [type: string]: CmdEvaluator } = {
253
254
_control : Control ,
254
255
_stash : Stash
255
256
) => {
257
+ let mtdClosure
258
+ // Native method handling
259
+ if ( isNativeMethodDeclaration ( command ) ) {
260
+ const FQMtdDesc = getFullyQualifiedDescriptor ( environment . current . name , command )
261
+ const fn = foreigns [ FQMtdDesc ]
262
+
263
+ if ( fn === undefined ) {
264
+ throw new errors . UndefinedNativeMethod ( FQMtdDesc )
265
+ }
266
+
267
+ // bind foreign function
268
+ const natDecl : NativeDeclaration = {
269
+ kind : 'NativeDeclaration' ,
270
+ methodModifier : command . methodModifier ,
271
+ methodHeader : command . methodHeader ,
272
+ foreignFunction : fn
273
+ }
274
+
275
+ mtdClosure = struct . closureStruct ( natDecl , environment . current )
276
+ } else {
277
+ mtdClosure = struct . closureStruct ( command , environment . current )
278
+ }
279
+
256
280
// Use method descriptor as key.
257
281
const mtdDescriptor : string = getDescriptor ( command )
258
- const mtdClosure = struct . closureStruct ( command , environment . current )
259
282
environment . defineMtdOrCon ( mtdDescriptor , mtdClosure )
260
283
} ,
261
284
@@ -471,13 +494,13 @@ export const cmdEvaluators: { [type: string]: CmdEvaluator } = {
471
494
const closure : Closure = stash . pop ( ) ! as Closure
472
495
473
496
const params : FormalParameter [ ] =
474
- closure . mtdOrCon . kind === 'MethodDeclaration'
475
- ? cloneDeep ( closure . mtdOrCon . methodHeader . formalParameterList )
476
- : cloneDeep ( closure . mtdOrCon . constructorDeclarator . formalParameterList )
497
+ closure . decl . kind === 'MethodDeclaration' || closure . decl . kind === 'NativeDeclaration '
498
+ ? cloneDeep ( closure . decl . methodHeader . formalParameterList )
499
+ : cloneDeep ( closure . decl . constructorDeclarator . formalParameterList )
477
500
478
501
// Extend env from global frame.
479
- const mtdOrConDescriptor = getDescriptor ( closure . mtdOrCon )
480
- environment . extendEnv ( environment . global , mtdOrConDescriptor )
502
+ const methodDescriptor = getDescriptor ( closure . decl )
503
+ environment . extendEnv ( environment . global , methodDescriptor )
481
504
482
505
const isInstanceMtdOrCon = args . length == params . length + 1
483
506
if ( isInstanceMtdOrCon ) {
@@ -504,17 +527,10 @@ export const cmdEvaluators: { [type: string]: CmdEvaluator } = {
504
527
environment . defineVariable ( params [ i ] . identifier , params [ i ] . unannType , args [ i ] )
505
528
}
506
529
507
- // Native function escape hatch
508
- if ( closure . mtdOrCon . kind === 'MethodDeclaration' && isNative ( closure . mtdOrCon ) ) {
509
- const nativeFnDescriptor = getFullyQualifiedDescriptor ( closure . mtdOrCon )
510
- const nativeFn = natives [ nativeFnDescriptor ]
511
-
512
- if ( ! nativeFn ) {
513
- throw new errors . UndefinedNativeMethod ( nativeFnDescriptor )
514
- }
515
-
516
- // call foreign fn
517
- nativeFn ( { control, stash, environment } )
530
+ // Native functions
531
+ if ( closure . decl . kind === 'NativeDeclaration' ) {
532
+ // call foreign fn with CSE machine state
533
+ closure . decl . foreignFunction ( { control, stash, environment } )
518
534
519
535
// only because resetInstr demands one, never actually used
520
536
const superfluousReturnStatement : ReturnStatement = {
@@ -524,15 +540,14 @@ export const cmdEvaluators: { [type: string]: CmdEvaluator } = {
524
540
525
541
// handle return from native fn
526
542
control . push ( instr . resetInstr ( superfluousReturnStatement ) )
527
- return
543
+ } else {
544
+ // Push method/constructor body.
545
+ const body =
546
+ closure . decl . kind === 'MethodDeclaration'
547
+ ? closure . decl . methodBody
548
+ : closure . decl . constructorBody
549
+ control . push ( body )
528
550
}
529
-
530
- // Push method/constructor body.
531
- const body =
532
- closure . mtdOrCon . kind === 'MethodDeclaration'
533
- ? closure . mtdOrCon . methodBody
534
- : closure . mtdOrCon . constructorBody
535
- control . push ( body )
536
551
} ,
537
552
538
553
[ InstrType . ENV ] : (
@@ -811,7 +826,7 @@ export const cmdEvaluators: { [type: string]: CmdEvaluator } = {
811
826
stash . push ( closure )
812
827
813
828
// Post-processing required if overload resolved method is instance method.
814
- if ( isInstance ( closure . mtdOrCon as MethodDeclaration ) ) {
829
+ if ( isInstance ( closure . decl as MethodDeclaration ) ) {
815
830
// Increment arity of InvInstr on control.
816
831
let n = 1
817
832
while (
@@ -834,7 +849,7 @@ export const cmdEvaluators: { [type: string]: CmdEvaluator } = {
834
849
const target = stash . pop ( ) !
835
850
const overloadResolvedClosure = stash . pop ( ) ! as Closure
836
851
837
- if ( isStatic ( overloadResolvedClosure . mtdOrCon as MethodDeclaration ) ) {
852
+ if ( isStatic ( overloadResolvedClosure . decl as MethodDeclaration ) ) {
838
853
// No method overriding resolution is required if resolved method is a static method.
839
854
stash . push ( overloadResolvedClosure )
840
855
return
0 commit comments