11import {
22 compileCall as compileBuiltinCall ,
3- compileGetGlobal as compileBuiltinGetGlobal
3+ compileGetConstant as compileBuiltinGetConstant
44} from "./builtins" ;
55
66import {
@@ -37,7 +37,8 @@ import {
3737 Local ,
3838 Namespace ,
3939 Parameter ,
40- EnumValue
40+ EnumValue ,
41+ Property
4142} from "./program" ;
4243
4344import {
@@ -49,7 +50,8 @@ import {
4950 NodeKind ,
5051 TypeNode ,
5152 Source ,
52- // statements
53+
54+ Statement ,
5355 BlockStatement ,
5456 BreakStatement ,
5557 ClassDeclaration ,
@@ -70,7 +72,6 @@ import {
7072 ModifierKind ,
7173 NamespaceDeclaration ,
7274 ReturnStatement ,
73- Statement ,
7475 SwitchCase ,
7576 SwitchStatement ,
7677 ThrowStatement ,
@@ -79,12 +80,12 @@ import {
7980 VariableDeclaration ,
8081 VariableStatement ,
8182 WhileStatement ,
82- // expressions
83+
84+ Expression ,
8385 AssertionExpression ,
8486 BinaryExpression ,
8587 CallExpression ,
8688 ElementAccessExpression ,
87- Expression ,
8889 FloatLiteralExpression ,
8990 IdentifierExpression ,
9091 IntegerLiteralExpression ,
@@ -97,7 +98,7 @@ import {
9798 StringLiteralExpression ,
9899 UnaryPostfixExpression ,
99100 UnaryPrefixExpression ,
100- // utility
101+
101102 hasModifier
102103} from "./ast" ;
103104
@@ -340,7 +341,7 @@ export class Compiler extends DiagnosticEmitter {
340341 }
341342
342343 compileGlobal ( global : Global ) : bool {
343- if ( global . isCompiled || ( global . isBuiltIn && compileBuiltinGetGlobal ( this , global ) ) )
344+ if ( global . isCompiled || ( global . isBuiltIn && compileBuiltinGetConstant ( this , global ) ) )
344345 return true ;
345346
346347 const declaration : VariableLikeDeclarationStatement | null = global . declaration ;
@@ -582,6 +583,21 @@ export class Compiler extends DiagnosticEmitter {
582583 return true ;
583584 }
584585
586+ // compilePropertyUsingTypeArguments(prototype: PropertyPrototype, contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): Function | null {
587+ // let getter: Function | null = null;
588+ // let setter: Function | null = null;
589+ // if (prototype.getterPrototype) {
590+ // getter = prototype.getterPrototype.resolve([], contextualTypeArguments); // reports
591+ // if (prototype.setterPrototype)
592+ // setter = prototype.setterPrototype.resolve([], contextualTypeArguments); // reports
593+ // }
594+
595+ // }
596+
597+ // compileProperty(instance: Property): bool {
598+
599+ // }
600+
585601 // namespaces
586602
587603 compileNamespaceDeclaration ( declaration : NamespaceDeclaration ) : void {
@@ -1625,37 +1641,83 @@ export class Compiler extends DiagnosticEmitter {
16251641 compileAssignment ( expression : Expression , valueExpression : Expression , contextualType : Type ) : ExpressionRef {
16261642 let element : Element | null = null ;
16271643 switch ( expression . kind ) {
1644+
16281645 case NodeKind . IDENTIFIER :
16291646 element = this . program . resolveIdentifier ( < IdentifierExpression > expression , this . currentFunction ) ; // reports
16301647 break ;
1648+
16311649 case NodeKind . PROPERTYACCESS :
16321650 element = this . program . resolvePropertyAccess ( < PropertyAccessExpression > expression , this . currentFunction ) ; // reports
16331651 break ;
1652+
16341653 default :
16351654 this . error ( DiagnosticCode . Operation_not_supported , expression . range ) ;
16361655 }
16371656 if ( ! element )
16381657 return this . module . createUnreachable ( ) ;
1658+
16391659 let type : Type | null = null ;
16401660 switch ( element . kind ) {
1661+
16411662 case ElementKind . LOCAL :
16421663 type = ( < Local > element ) . type ;
16431664 break ;
1665+
16441666 case ElementKind . GLOBAL :
16451667 if ( this . compileGlobal ( < Global > element ) )
16461668 type = ( < Global > element ) . type ;
16471669 break ;
1670+
1671+ case ElementKind . PROPERTY :
1672+ const setterPrototype : FunctionPrototype | null = ( < Property > element ) . setterPrototype ;
1673+ if ( setterPrototype ) {
1674+ const setterInstance : Function | null = setterPrototype . resolve ( ) ; // reports
1675+ if ( setterInstance ) {
1676+ if ( contextualType == Type . void ) { // just set if dropped anyway
1677+ return this . compileCall ( setterInstance , [ valueExpression ] , expression ) ;
1678+ } else { // otherwise do a set followed by a get
1679+ const getterPrototype : FunctionPrototype | null = ( < Property > element ) . getterPrototype ;
1680+ if ( getterPrototype ) {
1681+ const getterInstance : Function | null = getterPrototype . resolve ( ) ; // reports
1682+ if ( getterInstance ) {
1683+ return this . module . createBlock ( null , [
1684+ this . compileCall ( setterInstance , [ valueExpression ] , expression ) ,
1685+ this . compileCall ( getterInstance , [ ] , expression )
1686+ ] , getterInstance . returnType . toNativeType ( ) ) ;
1687+ }
1688+ } else
1689+ this . error ( DiagnosticCode . Property_0_does_not_exist_on_type_1 , expression . range , ( < Property > element ) . simpleName , ( < Property > element ) . parent . internalName ) ;
1690+ }
1691+ }
1692+ } else
1693+ this . error ( DiagnosticCode . Property_0_does_not_exist_on_type_1 , expression . range , ( < Property > element ) . simpleName , ( < Property > element ) . parent . internalName ) ;
1694+ return this . module . createUnreachable ( ) ;
1695+
16481696 default :
16491697 this . error ( DiagnosticCode . Operation_not_supported , expression . range ) ;
16501698 }
16511699 if ( ! type )
16521700 return this . module . createUnreachable ( ) ;
1701+
16531702 this . currentType = type ;
16541703 return this . compileAssignmentWithValue ( expression , this . compileExpression ( valueExpression , type , ConversionKind . IMPLICIT ) , contextualType != Type . void ) ;
16551704 }
16561705
16571706 compileAssignmentWithValue ( expression : Expression , valueWithCorrectType : ExpressionRef , tee : bool = false ) : ExpressionRef {
1658- const element : Element | null = this . program . resolveElement ( expression , this . currentFunction ) ;
1707+ let element : Element | null = null ;
1708+ switch ( expression . kind ) {
1709+
1710+ case NodeKind . IDENTIFIER :
1711+ element = this . program . resolveIdentifier ( < IdentifierExpression > expression , this . currentFunction ) ;
1712+ break ;
1713+
1714+ case NodeKind . PROPERTYACCESS :
1715+ element = this . program . resolvePropertyAccess ( < PropertyAccessExpression > expression , this . currentFunction ) ;
1716+ break ;
1717+
1718+ default :
1719+ this . error ( DiagnosticCode . Operation_not_supported , expression . range ) ;
1720+ }
16591721 if ( ! element )
16601722 return this . module . createUnreachable ( ) ;
16611723
@@ -1693,7 +1755,21 @@ export class Compiler extends DiagnosticEmitter {
16931755 }
16941756
16951757 compileCallExpression ( expression : CallExpression , contextualType : Type ) : ExpressionRef {
1696- const element : Element | null = this . program . resolveElement ( expression . expression , this . currentFunction ) ; // reports
1758+ let element : Element | null = null ;
1759+ switch ( expression . expression . kind ) {
1760+ // case NodeKind.SUPER:
1761+
1762+ case NodeKind . IDENTIFIER :
1763+ element = this . program . resolveIdentifier ( < IdentifierExpression > expression . expression , this . currentFunction ) ;
1764+ break ;
1765+
1766+ case NodeKind . PROPERTYACCESS :
1767+ element = this . program . resolvePropertyAccess ( < PropertyAccessExpression > expression . expression , this . currentFunction ) ;
1768+ break ;
1769+
1770+ default :
1771+ throw new Error ( "not implemented" ) ;
1772+ }
16971773 if ( ! element )
16981774 return this . module . createUnreachable ( ) ;
16991775
@@ -1837,7 +1913,7 @@ export class Compiler extends DiagnosticEmitter {
18371913 // global
18381914 if ( element . kind == ElementKind . GLOBAL ) {
18391915 if ( element . isBuiltIn )
1840- return compileBuiltinGetGlobal ( this , < Global > element ) ;
1916+ return compileBuiltinGetConstant ( this , < Global > element ) ;
18411917
18421918 const global : Global = < Global > element ;
18431919 if ( ! this . compileGlobal ( global ) ) // reports
@@ -1984,16 +2060,17 @@ export class Compiler extends DiagnosticEmitter {
19842060 if ( target . members ) {
19852061 element = target . members . get ( propertyName ) ;
19862062 if ( ! element ) {
1987- this . error ( DiagnosticCode . Property_0_does_not_exist_on_type_1 , propertyAccess . property . range , propertyName ) ;
2063+ this . error ( DiagnosticCode . Property_0_does_not_exist_on_type_1 , propertyAccess . property . range , propertyName , target . internalName ) ;
19882064 return this . module . createUnreachable ( ) ;
19892065 }
19902066
19912067 // handle enum values right away
19922068 if ( element . kind == ElementKind . ENUMVALUE ) {
19932069 this . currentType = Type . i32 ;
1994- return ( < EnumValue > element ) . hasConstantValue
1995- ? this . module . createI32 ( ( < EnumValue > element ) . constantValue )
1996- : this . module . createGetGlobal ( ( < EnumValue > element ) . internalName , NativeType . I32 ) ;
2070+ if ( ( < EnumValue > element ) . hasConstantValue )
2071+ return this . module . createI32 ( ( < EnumValue > element ) . constantValue )
2072+ this . compileEnum ( ( < EnumValue > element ) . enum ) ;
2073+ return this . module . createGetGlobal ( ( < EnumValue > element ) . internalName , NativeType . I32 ) ;
19972074 }
19982075 } else {
19992076 this . error ( DiagnosticCode . Property_0_does_not_exist_on_type_1 , propertyAccess . property . range , propertyName , target . internalName ) ;
@@ -2013,21 +2090,26 @@ export class Compiler extends DiagnosticEmitter {
20132090 return this . module . createUnreachable ( ) ;
20142091 this . currentType = < Type > ( < Global > element ) . type ;
20152092 if ( ( < Global > element ) . hasConstantValue )
2016- return this . currentType == Type . f32
2017- ? this . module . createF32 ( ( < Global > element ) . constantFloatValue )
2018- : this . currentType == Type . f64
2019- ? this . module . createF64 ( ( < Global > element ) . constantFloatValue )
2020- : this . currentType . isLongInteger
2021- ? this . module . createI64 ( ( < I64 > ( < Global > element ) . constantIntegerValue ) . lo , ( < I64 > ( < Global > element ) . constantIntegerValue ) . hi )
2022- : this . module . createI32 ( ( < I64 > ( < Global > element ) . constantIntegerValue ) . lo ) ;
2093+ return this . currentType == Type . f32 ? this . module . createF32 ( ( < Global > element ) . constantFloatValue )
2094+ : this . currentType == Type . f64 ? this . module . createF64 ( ( < Global > element ) . constantFloatValue )
2095+ : this . currentType . isLongInteger
2096+ ? this . module . createI64 ( ( < I64 > ( < Global > element ) . constantIntegerValue ) . lo , ( < I64 > ( < Global > element ) . constantIntegerValue ) . hi )
2097+ : this . module . createI32 ( ( < I64 > ( < Global > element ) . constantIntegerValue ) . lo ) ;
20232098 return this . module . createGetGlobal ( ( < Global > element ) . internalName , this . currentType . toNativeType ( ) ) ;
20242099
2025- case ElementKind . FUNCTION : // getter
2026- if ( ! ( < Function > element ) . prototype . isGetter ) {
2027- this . error ( DiagnosticCode . Property_0_does_not_exist_on_type_1 , propertyAccess . property . range , propertyName , element . internalName ) ;
2100+ case ElementKind . PROPERTY : // getter
2101+ const getterPrototype : FunctionPrototype | null = ( < Property > element ) . getterPrototype ;
2102+ if ( getterPrototype ) {
2103+ const getterInstance : Function | null = getterPrototype . resolve ( [ ] , this . currentFunction . contextualTypeArguments ) ;
2104+ if ( getterInstance ) {
2105+ return this . compileCall ( getterInstance , [ ] , propertyAccess ) ;
2106+ } else {
2107+ return this . module . createUnreachable ( ) ;
2108+ }
2109+ } else {
2110+ this . error ( DiagnosticCode . Property_0_does_not_exist_on_type_1 , propertyAccess . property . range , propertyName , target . internalName ) ;
20282111 return this . module . createUnreachable ( ) ;
20292112 }
2030- return this . compileCall ( < Function > element , [ ] , propertyAccess ) ;
20312113 }
20322114 this . error ( DiagnosticCode . Operation_not_supported , propertyAccess . range ) ;
20332115 throw new Error ( "not implemented" ) ;
0 commit comments