You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
1.9 KiB

2 years ago
import NodeFunction from '../core/NodeFunction.js';
import NodeFunctionInput from '../core/NodeFunctionInput.js';
const declarationRegexp = /^[fn]*\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)\s*[\-\>]*\s*([a-z_0-9]+)?/i;
const propertiesRegexp = /[a-z_0-9]+/ig;
const wgslTypeLib = {
f32: 'float'
};
const parse = ( source ) => {
source = source.trim();
const declaration = source.match( declarationRegexp );
if ( declaration !== null && declaration.length === 4 ) {
// tokenizer
const inputsCode = declaration[ 2 ];
const propsMatches = [];
let nameMatch = null;
while ( ( nameMatch = propertiesRegexp.exec( inputsCode ) ) !== null ) {
propsMatches.push( nameMatch );
}
// parser
const inputs = [];
let i = 0;
while ( i < propsMatches.length ) {
// default
const name = propsMatches[ i ++ ][ 0 ];
let type = propsMatches[ i ++ ][ 0 ];
type = wgslTypeLib[ type ] || type;
// precision
if ( i < propsMatches.length && /^[fui]\d{2}$/.test( propsMatches[ i ][ 0 ] ) === true )
i ++;
// add input
inputs.push( new NodeFunctionInput( type, name ) );
}
//
const blockCode = source.substring( declaration[ 0 ].length );
const name = declaration[ 1 ] !== undefined ? declaration[ 1 ] : '';
const type = declaration[ 3 ] || 'void';
return {
type,
inputs,
name,
inputsCode,
blockCode
};
} else {
throw new Error( 'FunctionNode: Function is not a WGSL code.' );
}
};
class WGSLNodeFunction extends NodeFunction {
constructor( source ) {
const { type, inputs, name, inputsCode, blockCode } = parse( source );
super( type, inputs, name );
this.inputsCode = inputsCode;
this.blockCode = blockCode;
}
getCode( name = this.name ) {
const type = this.type !== 'void' ? '-> ' + this.type : '';
return `fn ${ name } ( ${ this.inputsCode.trim() } ) ${ type }` + this.blockCode;
}
}
export default WGSLNodeFunction;