| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631 |
- import { toFloatType } from './TranspilerUtils.js';
- export class ASTNode {
- constructor() {
- this.isASTNode = true;
- this.linker = {
- reference: null,
- accesses: [],
- assignments: []
- };
- this.parent = null;
- }
- get isNumericExpression() {
- return false;
- }
- get hasAssignment() {
- if ( this.isAssignment === true ) {
- return true;
- }
- if ( this.parent === null ) {
- return false;
- }
- return this.parent.hasAssignment;
- }
- getType() {
- return this.type || null;
- }
- getParent( parents = [] ) {
- if ( this.parent === null ) {
- return parents;
- }
- parents.push( this.parent );
- return this.parent.getParent( parents );
- }
- initialize() {
- for ( const key in this ) {
- if ( this[ key ] && this[ key ].isASTNode ) {
- this[ key ].parent = this;
- } else if ( Array.isArray( this[ key ] ) ) {
- const array = this[ key ];
- for ( const item of array ) {
- if ( item && item.isASTNode ) {
- item.parent = this;
- }
- }
- }
- }
- }
- }
- export class Comment extends ASTNode {
- constructor( comment ) {
- super();
- this.comment = comment;
- this.isComment = true;
- this.initialize();
- }
- }
- export class Program extends ASTNode {
- constructor( body = [] ) {
- super();
- this.body = body;
- this.isProgram = true;
- this.initialize();
- }
- }
- export class VariableDeclaration extends ASTNode {
- constructor( type, name, value = null, next = null, immutable = false ) {
- super();
- this.type = type;
- this.name = name;
- this.value = value;
- this.next = next;
- this.immutable = immutable;
- this.isVariableDeclaration = true;
- this.initialize();
- }
- get isAssignment() {
- return this.value !== null;
- }
- }
- export class Uniform extends ASTNode {
- constructor( type, name ) {
- super();
- this.type = type;
- this.name = name;
- this.isUniform = true;
- this.initialize();
- }
- }
- export class Varying extends ASTNode {
- constructor( type, name ) {
- super();
- this.type = type;
- this.name = name;
- this.isVarying = true;
- this.initialize();
- }
- }
- export class FunctionParameter extends ASTNode {
- constructor( type, name, qualifier = null, immutable = true ) {
- super();
- this.type = type;
- this.name = name;
- this.qualifier = qualifier;
- this.immutable = immutable;
- this.isFunctionParameter = true;
- this.initialize();
- }
- }
- export class FunctionDeclaration extends ASTNode {
- constructor( type, name, params = [], body = [] ) {
- super();
- this.type = type;
- this.name = name;
- this.params = params;
- this.body = body;
- this.isFunctionDeclaration = true;
- this.initialize();
- }
- }
- export class Expression extends ASTNode {
- constructor( expression ) {
- super();
- this.expression = expression;
- this.isExpression = true;
- this.initialize();
- }
- }
- export class Ternary extends ASTNode {
- constructor( cond, left, right ) {
- super();
- this.cond = cond;
- this.left = left;
- this.right = right;
- this.isTernary = true;
- this.initialize();
- }
- }
- export class Operator extends ASTNode {
- constructor( type, left, right ) {
- super();
- this.type = type;
- this.left = left;
- this.right = right;
- this.isOperator = true;
- this.initialize();
- }
- get isAssignment() {
- return /^(=|\+=|-=|\*=|\/=|%=|<<=|>>=|>>>=|&=|\^=|\|=)$/.test( this.type );
- }
- get isNumericExpression() {
- if ( this.left.isNumericExpression && this.right.isNumericExpression ) {
- return true;
- }
- return false;
- }
- getType() {
- const leftType = this.left.getType();
- const rightType = this.right.getType();
- if ( leftType === rightType ) {
- return leftType;
- } else if ( toFloatType( leftType ) === toFloatType( rightType ) ) {
- return toFloatType( leftType );
- }
- return null;
- }
- }
- export class Unary extends ASTNode {
- constructor( type, expression, after = false ) {
- super();
- this.type = type;
- this.expression = expression;
- this.after = after;
- this.isUnary = true;
- this.initialize();
- }
- get isAssignment() {
- return /^(\+\+|--)$/.test( this.type );
- }
- get isNumericExpression() {
- if ( this.expression.isNumber ) {
- return true;
- }
- return false;
- }
- }
- export class Number extends ASTNode {
- constructor( value, type = 'float' ) {
- super();
- this.type = type;
- this.value = value;
- this.isNumber = true;
- this.initialize();
- }
- get isNumericExpression() {
- return true;
- }
- }
- export class String extends ASTNode {
- constructor( value ) {
- super();
- this.value = value;
- this.isString = true;
- this.initialize();
- }
- }
- export class Conditional extends ASTNode {
- constructor( cond = null, body = [] ) {
- super();
- this.cond = cond;
- this.body = body;
- this.elseConditional = null;
- this.isConditional = true;
- this.initialize();
- }
- }
- export class FunctionCall extends ASTNode {
- constructor( name, params = [] ) {
- super();
- this.name = name;
- this.params = params;
- this.isFunctionCall = true;
- this.initialize();
- }
- }
- export class Return extends ASTNode {
- constructor( value ) {
- super();
- this.value = value;
- this.isReturn = true;
- this.initialize();
- }
- }
- export class Discard extends ASTNode {
- constructor() {
- super();
- this.isDiscard = true;
- this.initialize();
- }
- }
- export class Continue extends ASTNode {
- constructor() {
- super();
- this.isContinue = true;
- this.initialize();
- }
- }
- export class Break extends ASTNode {
- constructor() {
- super();
- this.isBreak = true;
- this.initialize();
- }
- }
- export class Accessor extends ASTNode {
- constructor( property ) {
- super();
- this.property = property;
- this.isAccessor = true;
- this.initialize();
- }
- getType() {
- if ( this.linker.reference ) {
- return this.linker.reference.getType();
- }
- return super.getType();
- }
- }
- export class StaticElement extends ASTNode {
- constructor( value ) {
- super();
- this.value = value;
- this.isStaticElement = true;
- this.initialize();
- }
- }
- export class DynamicElement extends ASTNode {
- constructor( value ) {
- super();
- this.value = value;
- this.isDynamicElement = true;
- this.initialize();
- }
- }
- export class AccessorElements extends ASTNode {
- constructor( object, elements = [] ) {
- super();
- this.object = object;
- this.elements = elements;
- this.isAccessorElements = true;
- this.initialize();
- }
- }
- export class For extends ASTNode {
- constructor( initialization, condition, afterthought, body = [] ) {
- super();
- this.initialization = initialization;
- this.condition = condition;
- this.afterthought = afterthought;
- this.body = body;
- this.isFor = true;
- this.initialize();
- }
- }
- export class While extends ASTNode {
- constructor( condition, body = [] ) {
- super();
- this.condition = condition;
- this.body = body;
- this.isWhile = true;
- this.initialize();
- }
- }
- export class Switch extends ASTNode {
- constructor( discriminant, cases ) {
- super();
- this.discriminant = discriminant;
- this.cases = cases;
- this.isSwitch = true;
- this.initialize();
- }
- }
- export class SwitchCase extends ASTNode {
- constructor( body, conditions = null ) {
- super();
- this.body = body;
- this.conditions = conditions;
- this.isDefault = conditions === null ? true : false;
- this.isSwitchCase = true;
- this.initialize();
- }
- }
|