WGSLNodeFunction.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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 wgslTypeLib = {
  6. f32: 'float'
  7. };
  8. const parse = ( source ) => {
  9. source = source.trim();
  10. const declaration = source.match( declarationRegexp );
  11. if ( declaration !== null && declaration.length === 4 ) {
  12. // tokenizer
  13. const inputsCode = declaration[ 2 ];
  14. const propsMatches = [];
  15. let nameMatch = null;
  16. while ( ( nameMatch = propertiesRegexp.exec( inputsCode ) ) !== null ) {
  17. propsMatches.push( nameMatch );
  18. }
  19. // parser
  20. const inputs = [];
  21. let i = 0;
  22. while ( i < propsMatches.length ) {
  23. // default
  24. const name = propsMatches[ i ++ ][ 0 ];
  25. let type = propsMatches[ i ++ ][ 0 ];
  26. type = wgslTypeLib[ type ] || type;
  27. // precision
  28. if ( i < propsMatches.length && /^[fui]\d{2}$/.test( propsMatches[ i ][ 0 ] ) === true )
  29. i ++;
  30. // add input
  31. inputs.push( new NodeFunctionInput( type, name ) );
  32. }
  33. //
  34. const blockCode = source.substring( declaration[ 0 ].length );
  35. const name = declaration[ 1 ] !== undefined ? declaration[ 1 ] : '';
  36. const type = declaration[ 3 ] || 'void';
  37. return {
  38. type,
  39. inputs,
  40. name,
  41. inputsCode,
  42. blockCode
  43. };
  44. } else {
  45. throw new Error( 'FunctionNode: Function is not a WGSL code.' );
  46. }
  47. };
  48. class WGSLNodeFunction extends NodeFunction {
  49. constructor( source ) {
  50. const { type, inputs, name, inputsCode, blockCode } = parse( source );
  51. super( type, inputs, name );
  52. this.inputsCode = inputsCode;
  53. this.blockCode = blockCode;
  54. }
  55. getCode( name = this.name ) {
  56. const type = this.type !== 'void' ? '-> ' + this.type : '';
  57. return `fn ${ name } ( ${ this.inputsCode.trim() } ) ${ type }` + this.blockCode;
  58. }
  59. }
  60. export default WGSLNodeFunction;