@@ -119,7 +119,7 @@ export class Options {
119
119
/** If true, compiles everything instead of just reachable code. */
120
120
noTreeShaking : bool = false ;
121
121
/** If true, replaces assertions with nops. */
122
- noDebug : bool = false ;
122
+ noAssert : bool = false ;
123
123
}
124
124
125
125
const enum ConversionKind {
@@ -306,7 +306,7 @@ export class Compiler extends DiagnosticEmitter {
306
306
throw new Error ( "unexpected missing global" ) ;
307
307
if ( ! this . compileGlobal ( < Global > element ) )
308
308
return null ;
309
- if ( declaration . range . source . isEntry && ( < VariableStatement > declaration . parent ) . parent == declaration . range . source && hasModifier ( ModifierKind . EXPORT , declaration . modifiers ) ) {
309
+ if ( isModuleExport ( element , declaration ) ) {
310
310
if ( ( < Global > element ) . hasConstantValue )
311
311
this . module . addGlobalExport ( element . internalName , declaration . identifier . name ) ;
312
312
else
@@ -470,7 +470,7 @@ export class Compiler extends DiagnosticEmitter {
470
470
const instance : Function | null = this . compileFunctionUsingTypeArguments ( < FunctionPrototype > element , typeArguments , contextualTypeArguments , alternativeReportNode ) ;
471
471
if ( ! instance )
472
472
return ;
473
- if ( declaration . range . source . isEntry && declaration . parent == declaration . range . source && hasModifier ( ModifierKind . EXPORT , declaration . modifiers ) )
473
+ if ( isModuleExport ( instance , declaration ) )
474
474
this . module . addFunctionExport ( instance . internalName , declaration . identifier . name ) ;
475
475
}
476
476
@@ -527,7 +527,7 @@ export class Compiler extends DiagnosticEmitter {
527
527
528
528
// create the function
529
529
const internalName : string = instance . internalName ;
530
- if ( instance . isDeclared ) {
530
+ if ( instance . isDeclared ) { // TODO: use parent namespace as externalModuleName, if applicable
531
531
this . module . addFunctionImport ( internalName , "env" , declaration . identifier . name , typeRef ) ;
532
532
} else {
533
533
this . module . addFunction ( internalName , typeRef , typesToNativeTypes ( instance . additionalLocals ) , this . module . createBlock ( null , < ExpressionRef [ ] > stmts , NativeType . None ) ) ;
@@ -573,7 +573,6 @@ export class Compiler extends DiagnosticEmitter {
573
573
throw new Error ( "unexpected namespace member" ) ;
574
574
}
575
575
}
576
- throw new Error ( "not implemented" ) ;
577
576
}
578
577
579
578
compileNamespace ( ns : Namespace ) : void {
@@ -1834,7 +1833,115 @@ export class Compiler extends DiagnosticEmitter {
1834
1833
return this . compileExpression ( expression . expression , contextualType , ConversionKind . NONE ) ;
1835
1834
}
1836
1835
1837
- compilePropertyAccessExpression ( expression : PropertyAccessExpression , contextualType : Type ) : ExpressionRef {
1836
+ compilePropertyAccessExpression ( propertyAccess : PropertyAccessExpression , contextualType : Type ) : ExpressionRef {
1837
+ const expression : Expression = propertyAccess . expression ;
1838
+ const propertyName : string = propertyAccess . property . name ;
1839
+
1840
+ // the lhs expression is either 'this', 'super', an identifier or another property access
1841
+ let target : Element | null ;
1842
+ switch ( expression . kind ) {
1843
+
1844
+ default :
1845
+ throw new Error ( "unexpected expression kind" ) ;
1846
+
1847
+ case NodeKind . THIS :
1848
+ if ( ! this . currentFunction . instanceMethodOf ) {
1849
+ this . error ( DiagnosticCode . _this_cannot_be_referenced_in_current_location , expression . range ) ;
1850
+ return this . module . createUnreachable ( ) ;
1851
+ }
1852
+ target = this . currentFunction . instanceMethodOf ;
1853
+ break ;
1854
+
1855
+ case NodeKind . SUPER :
1856
+ if ( ! ( this . currentFunction . instanceMethodOf && this . currentFunction . instanceMethodOf . base ) ) {
1857
+ this . error ( DiagnosticCode . _super_can_only_be_referenced_in_a_derived_class , expression . range ) ;
1858
+ return this . module . createUnreachable ( ) ;
1859
+ }
1860
+ target = this . currentFunction . instanceMethodOf . base ;
1861
+ break ;
1862
+
1863
+ case NodeKind . IDENTIFIER :
1864
+ target = this . program . resolveIdentifier ( < IdentifierExpression > expression , this . currentFunction ) ; // reports
1865
+ break ;
1866
+
1867
+ case NodeKind . PROPERTYACCESS :
1868
+ target = this . program . resolvePropertyAccess ( < PropertyAccessExpression > expression , this . currentFunction ) ; // reports
1869
+ break ;
1870
+ }
1871
+ if ( ! target )
1872
+ return this . module . createUnreachable ( ) ;
1873
+
1874
+ // look up the property within the target to obtain the actual element
1875
+ let element : Element | null ;
1876
+ let expr : ExpressionRef ;
1877
+ switch ( target . kind ) {
1878
+
1879
+ // handle enum value right away
1880
+
1881
+ case ElementKind . ENUM :
1882
+ element = ( < Enum > target ) . members . get ( propertyName ) ;
1883
+ if ( ! element ) {
1884
+ this . error ( DiagnosticCode . Property_0_does_not_exist_on_type_1 , propertyAccess . property . range , propertyName ) ;
1885
+ return this . module . createUnreachable ( ) ;
1886
+ }
1887
+ this . currentType = Type . i32 ;
1888
+ return ( < EnumValue > element ) . hasConstantValue
1889
+ ? this . module . createI32 ( ( < EnumValue > element ) . constantValue )
1890
+ : this . module . createGetGlobal ( ( < EnumValue > element ) . internalName , NativeType . I32 ) ;
1891
+
1892
+ // postpone everything else
1893
+
1894
+ case ElementKind . LOCAL :
1895
+ element = ( < Local > target ) . type . classType ;
1896
+ if ( ! element ) {
1897
+ this . error ( DiagnosticCode . Property_0_does_not_exist_on_type_1 , propertyAccess . property . range , propertyName , ( < Local > target ) . type . toString ( ) ) ;
1898
+ return this . module . createUnreachable ( ) ;
1899
+ }
1900
+ target = element ;
1901
+ break ;
1902
+
1903
+ case ElementKind . GLOBAL :
1904
+ if ( ! this . compileGlobal ( < Global > target ) )
1905
+ return this . module . createUnreachable ( ) ;
1906
+ element = ( < Type > ( < Global > target ) . type ) . classType ;
1907
+ if ( ! element ) {
1908
+ this . error ( DiagnosticCode . Property_0_does_not_exist_on_type_1 , propertyAccess . property . range , propertyName , ( < Local > target ) . type . toString ( ) ) ;
1909
+ return this . module . createUnreachable ( ) ;
1910
+ }
1911
+ target = element ;
1912
+ break ;
1913
+
1914
+ case ElementKind . NAMESPACE :
1915
+ element = ( < Namespace > target ) . members . get ( propertyName ) ;
1916
+ if ( ! ( element && element . isExported ) ) {
1917
+ this . error ( DiagnosticCode . Namespace_0_has_no_exported_member_1 , propertyAccess . property . range , ( < Namespace > target ) . internalName , propertyName ) ;
1918
+ return this . module . createUnreachable ( ) ;
1919
+ }
1920
+ target = element ;
1921
+ break ;
1922
+
1923
+ default :
1924
+ throw new Error ( "unexpected target kind" ) ;
1925
+ }
1926
+
1927
+ // handle the element
1928
+ switch ( element . kind ) {
1929
+
1930
+ case ElementKind . LOCAL :
1931
+ return this . module . createGetLocal ( ( < Local > element ) . index , typeToNativeType ( this . currentType = ( < Local > element ) . type ) ) ;
1932
+
1933
+ case ElementKind . GLOBAL :
1934
+ this . compileGlobal ( < Global > element ) ;
1935
+ return this . module . createGetGlobal ( ( < Global > element ) . internalName , typeToNativeType ( this . currentType = < Type > ( < Global > element ) . type ) ) ;
1936
+
1937
+ case ElementKind . FUNCTION : // getter
1938
+ if ( ! ( < Function > element ) . prototype . isGetter ) {
1939
+ this . error ( DiagnosticCode . Property_0_does_not_exist_on_type_1 , propertyAccess . property . range , propertyName , element . internalName ) ;
1940
+ return this . module . createUnreachable ( ) ;
1941
+ }
1942
+ return this . compileCall ( < Function > element , [ ] , propertyAccess ) ;
1943
+ }
1944
+ this . error ( DiagnosticCode . Operation_not_supported , propertyAccess . range ) ;
1838
1945
throw new Error ( "not implemented" ) ;
1839
1946
}
1840
1947
@@ -2031,3 +2138,22 @@ function typesToSignatureName(paramTypes: Type[], returnType: Type): string {
2031
2138
sb . push ( typeToSignatureNamePart ( returnType ) ) ;
2032
2139
return sb . join ( "" ) ;
2033
2140
}
2141
+
2142
+ function isModuleExport ( element : Element , declaration : DeclarationStatement ) : bool {
2143
+ if ( ! element . isExported )
2144
+ return false ;
2145
+ if ( declaration . range . source . isEntry )
2146
+ return true ;
2147
+ let parentNode : Node | null = declaration . parent ;
2148
+ if ( ! parentNode )
2149
+ return false ;
2150
+ if ( parentNode . kind == NodeKind . VARIABLE )
2151
+ if ( ! ( parentNode = parentNode . parent ) )
2152
+ return false ;
2153
+ if ( parentNode . kind != NodeKind . NAMESPACE && parentNode . kind != NodeKind . CLASS )
2154
+ return false ;
2155
+ let parent : Element | null = element . program . elements . get ( ( < DeclarationStatement > parentNode ) . internalName ) ;
2156
+ if ( ! parent )
2157
+ return false ;
2158
+ return isModuleExport ( parent , < DeclarationStatement > parentNode ) ;
2159
+ }
0 commit comments