Skip to content

Commit

Permalink
Merge pull request #125 from Malacath-92/master
Browse files Browse the repository at this point in the history
Fix for numbers with exponents as floats
  • Loading branch information
stevensona authored Dec 22, 2020
2 parents dc65fe6 + 362db3a commit b28a228
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 157 deletions.
11 changes: 3 additions & 8 deletions .github/workflows/CI.yml → .github/workflows/BuildAndTest.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: CI
name: Build and Test

on:
push:
Expand All @@ -9,7 +9,7 @@ on:
types: [ created ]

jobs:
build:
build_and_test:
name: ${{ matrix.name }}

strategy:
Expand All @@ -30,7 +30,7 @@ jobs:
uses: actions/[email protected]

- name: Install Node.js
uses: actions/[email protected].2
uses: actions/[email protected].4
with:
node-version: 10.x

Expand All @@ -44,8 +44,3 @@ jobs:
uses: GabrielBB/[email protected]
with:
run: npm test
- name: Publish
if: success() && startsWith(github.ref, 'refs/tags/releases/') && matrix.os == 'ubuntu-latest'
run: npm run deploy
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
44 changes: 44 additions & 0 deletions .github/workflows/Publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Publish

on:
release:
types: [ created ]

jobs:
publish:
name: Publish

strategy:
matrix:
os: [ubuntu-latest]

runs-on: ${{ matrix.os }}

steps:
- name: Checkout
uses: actions/[email protected]

- name: Install Node.js
uses: actions/[email protected]
with:
node-version: 10.x

- name: Wait on tests
uses: lewagon/[email protected]
with:
ref: test_publish
check-name: Ubuntu
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 20 # seconds

- name: Install
run: npm install

- name: Build
run: npm run webpack

- name: Publish
if: success()
run: npm run deploy
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
# Visual Studio Code - Shader Toy
<p align="center">
<a href="https://github.com/stevensona/shader-toy/actions">
<img src="https://github.com/stevensona/shader-toy/workflows/Build%20and%20Test/badge.svg">
</a>
<a href="https://opensource.org/licenses/MIT" >
<img src="https://img.shields.io/apm/l/vim-mode.svg">
</a>
</p>

With this extension, view a live WebGL preview of GLSL shaders within VSCode, similar to [shadertoy.com](https://www.shadertoy.com/) by providing a "Show GLSL Preview" command.

Expand Down Expand Up @@ -50,7 +58,7 @@ If any of the six files can not be found, the next set is tried, starting from t

### Audio Input (experimental)
_Note: By default audio input is disabled, change the setting "Enable Audio Input" to use it._\
Audio input is only supported from within _Visual Studio Code_, since _ffmpeg_ is not shipped with _Visual Studio Code_
Audio input is not supported from within _Visual Studio Code_, since _ffmpeg_ is not shipped with _Visual Studio Code_, so you will have to generate a standalone version and host a local server to be able to load local files (or fiddle with your browsers security settings) if you want to use audio in your shaders.
If your channel defines audio input, it will be inferred from the file extension. The channel will be a `2` pixels high and `512` pixels wide texture, where the width can be adjusted by the "Audio Domain Size" setting. The first row containing the audios frequency spectrum and the second row containing its waveform.

### Keyboard Input
Expand Down Expand Up @@ -167,6 +175,10 @@ Contributions of any kind are welcome and encouraged.

## Release Notes

### 0.10.15
* Lex numbers with exponents as floating point, not integer,
* make assignability testing more robust.

### 0.10.14
* Hotfix, extension was trying to run a non-existant file.

Expand Down
5 changes: 1 addition & 4 deletions src/shaderlexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,8 @@ export class ShaderLexer {
return return_val;
});
let parsedNumber = parseFloat(number);
if (parsedNumber === NaN) {
console.log(number);
}
return {
type: has_dot ? TokenType.Float : TokenType.Integer,
type: has_dot || has_exponent ? TokenType.Float : TokenType.Integer,
value: parsedNumber
};
}
Expand Down
116 changes: 64 additions & 52 deletions src/shaderparser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ export class ShaderParser {
return nextValue;
}
defaultvalue = nextValue;
if (!ShaderParser.testAssignable(type, defaultvalue.ValueType)) {
if (!this.testAssignable(type, defaultvalue.ValueType)) {
return this.makeError(`Expected initializer of type assignable to "${type}" but got "${defaultvalue.LiteralString}" which is of type "${defaultvalue.ValueType}"`);
}
nextToken = this.lexer.peek();
Expand All @@ -323,10 +323,10 @@ export class ShaderParser {
}

[ minValue, maxValue ] = rangeArray.Value;
if (!ShaderParser.testAssignable(type, minValue.ValueType)) {
if (!this.testAssignable(type, minValue.ValueType)) {
return this.makeError(`Expected initializer of type "${type}" but got "${minValue.LiteralString}" which is of type ${minValue.ValueType}`);
}
if (!ShaderParser.testAssignable(type, maxValue.ValueType)) {
if (!this.testAssignable(type, maxValue.ValueType)) {
return this.makeError(`Expected initializer of type "${type}" but got "${maxValue.LiteralString}" which is of type ${maxValue.ValueType}`);
}
nextToken = this.lexer.peek();
Expand All @@ -339,7 +339,7 @@ export class ShaderParser {
return step;
}

if (!ShaderParser.testAssignable(type, step.ValueType)) {
if (!this.testAssignable(type, step.ValueType)) {
return this.makeError(`Expected initializer of type "${type}" but got "${step.LiteralString}" which is of type ${step.ValueType}`);
}

Expand Down Expand Up @@ -426,7 +426,7 @@ export class ShaderParser {
if (firstValue.Type === ObjectType.Error) {
return firstValue;
}
if (!ShaderParser.testAssignable(expectedType, firstValue.ValueType)) {
if (!this.testAssignable(expectedType, firstValue.ValueType)) {
return this.makeError(`Expected value assignable to type ${expectedType} but got ${firstValue.LiteralString} which is of type ${firstValue.Type}`);
}

Expand All @@ -445,7 +445,7 @@ export class ShaderParser {
if (nextValue.Type === ObjectType.Error) {
return nextValue;
}
if (!ShaderParser.testAssignable(expectedType, nextValue.ValueType)) {
if (!this.testAssignable(expectedType, nextValue.ValueType)) {
return this.makeError(`Expected value assignable to type ${firstValue.ValueType} but got ${nextValue.LiteralString} which is of type ${nextValue.ValueType}`);
}

Expand Down Expand Up @@ -516,7 +516,7 @@ export class ShaderParser {
if (currentValue.Type === ObjectType.Error) {
return currentValue;
}
if (!ShaderParser.testAssignable(type, currentValue.ValueType)) {
if (!this.testAssignable(type, currentValue.ValueType)) {
return this.makeError(`Expected value assignable to type ${type} but got "${currentValue.LiteralString}" which is of type ${currentValue.ValueType}`);
}

Expand Down Expand Up @@ -551,75 +551,87 @@ export class ShaderParser {
return error;
}

private static mapVecTypesToArrayTypes(type: string) {
private mapVecTypesToArrayTypes(type: string) {
if (type.indexOf('vec') === 0) {
return `float[${type[type.length - 1]}]`;
return [ `float[${type[type.length - 1]}]`, true ];
}
else if (type === 'color3') {
return `float[3]`;
return [ `float[3]`, true ];
}
else if (type.indexOf('ivec') === 0) {
return `int[${type[type.length - 1]}]`;
return [ `int[${type[type.length - 1]}]`, true ];
}
return type;
return [ type, false];
}

private static getArrayElementType(type: string) {
let first_bracket = type.indexOf('[');
return first_bracket >= 0 ? type.substring(0, first_bracket) : undefined;
}

private static testAssignable(leftType: string, rightType: string) {
private testAssignable(leftType: string, rightType: string) {
if (leftType === rightType) {
return true;
}

if (leftType === 'float' && rightType === 'int') {
return true;
}

leftType = this.mapVecTypesToArrayTypes(leftType);
rightType = this.mapVecTypesToArrayTypes(rightType);

{
let leftArrayElementType = this.getArrayElementType(leftType) || leftType;
let rightArrayElementType = this.getArrayElementType(rightType) || rightType;
let leftIsArrayType = leftArrayElementType !== leftType;
let rightIsArrayType = rightArrayElementType !== rightType;
if (leftIsArrayType || rightIsArrayType) {
let arrayElementTypesAssignable = this.testAssignable(leftArrayElementType, rightArrayElementType);
if (!arrayElementTypesAssignable) {
return false;
}
else if (leftIsArrayType !== rightIsArrayType) {
return true;
}
}
else if (leftType == 'int' && rightType == 'float') {
return false;
}

let lPos = 0;
while (leftType[lPos] === rightType[lPos] && leftType[lPos] !== '[') { lPos++; }
let [ leftMappedType, leftIsVecType ] = this.mapVecTypesToArrayTypes(leftType);
let [ rightMappedType, rightIsVecType ] = this.mapVecTypesToArrayTypes(rightType);

let isFirst = true;
type TypeDesc = {
BaseTypeName: string,
ArraySizes: number[]
};
let getTypeDesc = (typeName: string): TypeDesc => {
let elements = typeName.split('[');
let stripped_elements = elements.map((element: string, index: number) => {
if (index == 0)
return element
return element.slice(0, -1);
});
let baseTypeName = stripped_elements.shift();
let arraySizes = stripped_elements.map(s => Number(s));
return {
BaseTypeName: baseTypeName || "error",
ArraySizes: arraySizes
}
};
let leftTypeDesc = getTypeDesc(leftMappedType as string);
let rightTypeDesc = getTypeDesc(rightMappedType as string);

let rPos = lPos;
while (lPos !== leftType.length && rPos !== rightType.length) {
let lStart = lPos + 1;
while(leftType[lPos] !== ']') { lPos++; }
let lNumber = parseInt(leftType.substring(lStart, lPos - 1));
let leftIsArray = leftTypeDesc.ArraySizes.length > 0;
let rightIsArray = rightTypeDesc.ArraySizes.length > 0;

let rStart = lPos + 1;
while(rightType[rPos] !== ']') { rPos++; }
let rNumber = parseInt(rightType.substring(rStart, rPos - 1));
if (leftIsArray || rightIsArray) {
let arrayElementTypesAssignable = this.testAssignable(leftTypeDesc.BaseTypeName, rightTypeDesc.BaseTypeName);
if (!arrayElementTypesAssignable) {
return false;
}
}
else {
return false;
}

if (leftIsVecType as boolean && !rightIsArray && this.testAssignable(leftTypeDesc.BaseTypeName, rightTypeDesc.BaseTypeName)) {
return true;
}

if (isNaN(lNumber) && isFirst) { continue; }
if (leftTypeDesc.ArraySizes.length != rightTypeDesc.ArraySizes.length) {
return false;
}

if (isNaN(lNumber) || isNaN(rNumber)) { return false; }
if (lNumber !== rNumber) { return false; }
let leftUndefinedArraySize = leftTypeDesc.ArraySizes.indexOf(0);
if (leftUndefinedArraySize >= 0 && leftUndefinedArraySize < leftTypeDesc.ArraySizes.length - 1) {
return false;
}

isFirst = false;
let rightUndefinedArraySize = rightTypeDesc.ArraySizes.indexOf(0);
if (rightUndefinedArraySize >= 0 && rightUndefinedArraySize < rightTypeDesc.ArraySizes.length - 1) {
return false;
}

return lPos === leftType.length && rPos === rightType.length;
let arraySizesMatch = leftTypeDesc.ArraySizes.every((arraySize: number, index: number) => arraySize == 0 || arraySize == rightTypeDesc.ArraySizes[0]);
return arraySizesMatch;
}
}
Loading

0 comments on commit b28a228

Please sign in to comment.