WGSLNodeFunction.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import NodeFunction from '../core/NodeFunction.js';
  2. import NodeFunctionInput from '../core/NodeFunctionInput.js';
  3. const declarationRegexp = /^fn\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)\s*\-\>\s*([a-z_0-9]+)?/i;
  4. const propertiesRegexp = /[a-z_0-9]+/ig;
  5. const parse = ( source ) => {
  6. source = source.trim();
  7. const declaration = source.match( declarationRegexp );
  8. if ( declaration !== null && declaration.length === 4 ) {
  9. // tokenizer
  10. const inputsCode = declaration[ 2 ];
  11. const propsMatches = [];
  12. let nameMatch = null;
  13. while ( ( nameMatch = propertiesRegexp.exec( inputsCode ) ) !== null ) {
  14. propsMatches.push( nameMatch );
  15. }
  16. // parser
  17. const inputs = [];
  18. let i = 0;
  19. while ( i < propsMatches.length ) {
  20. const name = propsMatches[ i ++ ][ 0 ];
  21. const type = propsMatches[ i ++ ][ 0 ];
  22. propsMatches[ i ++ ][ 0 ]; // precision
  23. inputs.push( new NodeFunctionInput( type, name ) );
  24. }
  25. //
  26. const blockCode = source.substring( declaration[ 0 ].length );
  27. const name = declaration[ 1 ] !== undefined ? declaration[ 1 ] : '';
  28. const type = declaration[ 3 ];
  29. return {
  30. type,
  31. inputs,
  32. name,
  33. inputsCode,
  34. blockCode
  35. };
  36. } else {
  37. throw new Error( 'FunctionNode: Function is not a WGSL code.' );
  38. }
  39. };
  40. class WGSLNodeFunction extends NodeFunction {
  41. constructor( source ) {
  42. const { type, inputs, name, inputsCode, blockCode } = parse( source );
  43. super( type, inputs, name );
  44. this.inputsCode = inputsCode;
  45. this.blockCode = blockCode;
  46. }
  47. getCode( name = this.name ) {
  48. return `fn ${ name } ( ${ this.inputsCode.trim() } ) -> ${ this.type }` + this.blockCode;
  49. }
  50. }
  51. export default WGSLNodeFunction;