Switch to two arrays for instructions.
This commit is contained in:
		
							parent
							
								
									971f35d165
								
							
						
					
					
						commit
						27b0d0c941
					
				@ -360,7 +360,7 @@ var PDFFunction = (function PDFFunctionClosure() {
 | 
				
			|||||||
      var range = IR[2];
 | 
					      var range = IR[2];
 | 
				
			||||||
      var code = IR[3];
 | 
					      var code = IR[3];
 | 
				
			||||||
      var numOutputs = range.length / 2;
 | 
					      var numOutputs = range.length / 2;
 | 
				
			||||||
      var evaluator = new PostScriptEvaluator(code);
 | 
					      var evaluator = new PostScriptEvaluator(code[0], code[1]);
 | 
				
			||||||
      // Cache the values for a big speed up, the cache size is limited though
 | 
					      // Cache the values for a big speed up, the cache size is limited though
 | 
				
			||||||
      // since the number of possible values can be huge from a PS function.
 | 
					      // since the number of possible values can be huge from a PS function.
 | 
				
			||||||
      var cache = new FunctionCache();
 | 
					      var cache = new FunctionCache();
 | 
				
			||||||
@ -455,31 +455,36 @@ var PostScriptStack = (function PostScriptStack() {
 | 
				
			|||||||
  return PostScriptStack;
 | 
					  return PostScriptStack;
 | 
				
			||||||
})();
 | 
					})();
 | 
				
			||||||
var PostScriptEvaluator = (function PostScriptEvaluator() {
 | 
					var PostScriptEvaluator = (function PostScriptEvaluator() {
 | 
				
			||||||
  function PostScriptEvaluator(code) {
 | 
					  function PostScriptEvaluator(operators, operands) {
 | 
				
			||||||
    this.code = code;
 | 
					    this.operators = operators;
 | 
				
			||||||
    console.log(code);
 | 
					    this.operands = operands;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  PostScriptEvaluator.prototype = {
 | 
					  PostScriptEvaluator.prototype = {
 | 
				
			||||||
    execute: function(initialStack) {
 | 
					    execute: function(initialStack) {
 | 
				
			||||||
      var stack = new PostScriptStack(initialStack);
 | 
					      var stack = new PostScriptStack(initialStack);
 | 
				
			||||||
      var counter = 0;
 | 
					      var counter = 0;
 | 
				
			||||||
      var code = this.code;
 | 
					      var operators = this.operators;
 | 
				
			||||||
      var a, b;
 | 
					      var operands = this.operands;
 | 
				
			||||||
      while (counter < this.code.length) {
 | 
					      var length = operators.length;
 | 
				
			||||||
        var instruction = this.code[counter++];
 | 
					      var a, b, operand;
 | 
				
			||||||
        var operator = instruction[0];
 | 
					      while (counter < length) {
 | 
				
			||||||
 | 
					        var operator = operators[counter];
 | 
				
			||||||
 | 
					        ++counter;
 | 
				
			||||||
        switch (operator) {
 | 
					        switch (operator) {
 | 
				
			||||||
          // non standard ps operators
 | 
					          // non standard ps operators
 | 
				
			||||||
          case 'push':
 | 
					          case 'push':
 | 
				
			||||||
            stack.push(instruction[1]);
 | 
					            operand = operands[counter - 1];
 | 
				
			||||||
 | 
					            stack.push(operand);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
          case 'jz': // jump if false
 | 
					          case 'jz': // jump if false
 | 
				
			||||||
 | 
					            operand = operands[counter - 1];
 | 
				
			||||||
            a = stack.pop();
 | 
					            a = stack.pop();
 | 
				
			||||||
            if (!a)
 | 
					            if (!a)
 | 
				
			||||||
              counter = instruction[1];
 | 
					              counter = operand;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
          case 'j': // jump
 | 
					          case 'j': // jump
 | 
				
			||||||
            counter = instruction[1];
 | 
					            operand = operands[counter - 1];
 | 
				
			||||||
 | 
					            counter = operand;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          // all ps operators in alphabetical order (excluding if/ifelse)
 | 
					          // all ps operators in alphabetical order (excluding if/ifelse)
 | 
				
			||||||
@ -690,7 +695,8 @@ var PostScriptEvaluator = (function PostScriptEvaluator() {
 | 
				
			|||||||
var PostScriptParser = (function PostScriptParser() {
 | 
					var PostScriptParser = (function PostScriptParser() {
 | 
				
			||||||
  function PostScriptParser(lexer) {
 | 
					  function PostScriptParser(lexer) {
 | 
				
			||||||
    this.lexer = lexer;
 | 
					    this.lexer = lexer;
 | 
				
			||||||
    this.code = [];
 | 
					    this.operators = [];
 | 
				
			||||||
 | 
					    this.operands = [];
 | 
				
			||||||
    this.token;
 | 
					    this.token;
 | 
				
			||||||
    this.prev;
 | 
					    this.prev;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -717,14 +723,16 @@ var PostScriptParser = (function PostScriptParser() {
 | 
				
			|||||||
      this.expect(PostScriptTokenTypes.LBRACE);
 | 
					      this.expect(PostScriptTokenTypes.LBRACE);
 | 
				
			||||||
      this.parseBlock();
 | 
					      this.parseBlock();
 | 
				
			||||||
      this.expect(PostScriptTokenTypes.RBRACE);
 | 
					      this.expect(PostScriptTokenTypes.RBRACE);
 | 
				
			||||||
      return this.code;
 | 
					      return [this.operators, this.operands];
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    parseBlock: function parseBlock() {
 | 
					    parseBlock: function parseBlock() {
 | 
				
			||||||
      while (true) {
 | 
					      while (true) {
 | 
				
			||||||
        if (this.accept(PostScriptTokenTypes.NUMBER)) {
 | 
					        if (this.accept(PostScriptTokenTypes.NUMBER)) {
 | 
				
			||||||
          this.code.push(['push', this.prev.value]);
 | 
					          this.operators.push('push');
 | 
				
			||||||
 | 
					          this.operands.push(this.prev.value);
 | 
				
			||||||
        } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
 | 
					        } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
 | 
				
			||||||
          this.code.push([this.prev.value]);
 | 
					          this.operators.push(this.prev.value);
 | 
				
			||||||
 | 
					          this.operands.push(null);
 | 
				
			||||||
        } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
 | 
					        } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
 | 
				
			||||||
          this.parseCondition();
 | 
					          this.parseCondition();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@ -733,26 +741,33 @@ var PostScriptParser = (function PostScriptParser() {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    parseCondition: function parseCondition() {
 | 
					    parseCondition: function parseCondition() {
 | 
				
			||||||
      var counter = this.code.length - 1;
 | 
					      // Add two place holders that will be updated later
 | 
				
			||||||
      var condition = [];
 | 
					      var conditionLocation = this.operators.length;
 | 
				
			||||||
      this.code.push(condition);
 | 
					      this.operators.push(null);
 | 
				
			||||||
 | 
					      this.operands.push(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      this.parseBlock();
 | 
					      this.parseBlock();
 | 
				
			||||||
      this.expect(PostScriptTokenTypes.RBRACE);
 | 
					      this.expect(PostScriptTokenTypes.RBRACE);
 | 
				
			||||||
      if (this.accept(PostScriptTokenTypes.IF)) {
 | 
					      if (this.accept(PostScriptTokenTypes.IF)) {
 | 
				
			||||||
        // The true block is right after the 'if' so it just falls through on
 | 
					        // The true block is right after the 'if' so it just falls through on
 | 
				
			||||||
        // true else it jumps and skips the true block.
 | 
					        // true else it jumps and skips the true block.
 | 
				
			||||||
        condition.push('jz', this.code.length);
 | 
					        this.operators[conditionLocation] = 'jz';
 | 
				
			||||||
 | 
					        this.operands[conditionLocation] = this.operators.length;
 | 
				
			||||||
      } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
 | 
					      } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
 | 
				
			||||||
        var jump = [];
 | 
					        var jumpLocation = this.operators.length;
 | 
				
			||||||
        this.code.push(jump);
 | 
					        this.operators.push(null);
 | 
				
			||||||
        var endOfTrue = this.code.length;
 | 
					        this.operands.push(null);
 | 
				
			||||||
 | 
					        var endOfTrue = this.operators.length;
 | 
				
			||||||
        this.parseBlock();
 | 
					        this.parseBlock();
 | 
				
			||||||
        this.expect(PostScriptTokenTypes.RBRACE);
 | 
					        this.expect(PostScriptTokenTypes.RBRACE);
 | 
				
			||||||
        this.expect(PostScriptTokenTypes.IFELSE);
 | 
					        this.expect(PostScriptTokenTypes.IFELSE);
 | 
				
			||||||
        // The jump is added at the end of the true block to skip the false
 | 
					        // The jump is added at the end of the true block to skip the false
 | 
				
			||||||
        // block.
 | 
					        // block.
 | 
				
			||||||
        jump.push('j', this.code.length);
 | 
					        this.operators[jumpLocation] = 'j';
 | 
				
			||||||
        condition.push('jz', endOfTrue);
 | 
					        this.operands[jumpLocation] = this.operands.length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.operators[conditionLocation] = 'jz';
 | 
				
			||||||
 | 
					        this.operands[conditionLocation] = endOfTrue;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        error('PS Function: error parsing conditional.');
 | 
					        error('PS Function: error parsing conditional.');
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
				
			|||||||
@ -38,13 +38,13 @@ describe('function', function() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    it('parses empty programs', function() {
 | 
					    it('parses empty programs', function() {
 | 
				
			||||||
      var output = parse('{}');
 | 
					      var output = parse('{}');
 | 
				
			||||||
      expect(output.length).toEqual(0);
 | 
					      expect(output[0].length).toEqual(0);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it('parses positive numbers', function() {
 | 
					    it('parses positive numbers', function() {
 | 
				
			||||||
      var number = 999;
 | 
					      var number = 999;
 | 
				
			||||||
      var program = parse('{ ' + number + ' }');
 | 
					      var program = parse('{ ' + number + ' }');
 | 
				
			||||||
      var expectedProgram = [
 | 
					      var expectedProgram = [
 | 
				
			||||||
        ['push', number]
 | 
					        ['push'], [number]
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      expect(program).toMatchArray(expectedProgram);
 | 
					      expect(program).toMatchArray(expectedProgram);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@ -52,7 +52,7 @@ describe('function', function() {
 | 
				
			|||||||
      var number = -999;
 | 
					      var number = -999;
 | 
				
			||||||
      var program = parse('{ ' + number + ' }');
 | 
					      var program = parse('{ ' + number + ' }');
 | 
				
			||||||
      var expectedProgram = [
 | 
					      var expectedProgram = [
 | 
				
			||||||
        ['push', number]
 | 
					        ['push'], [number]
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      expect(program).toMatchArray(expectedProgram);
 | 
					      expect(program).toMatchArray(expectedProgram);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@ -60,32 +60,28 @@ describe('function', function() {
 | 
				
			|||||||
      var number = 3.3;
 | 
					      var number = 3.3;
 | 
				
			||||||
      var program = parse('{ ' + number + ' }');
 | 
					      var program = parse('{ ' + number + ' }');
 | 
				
			||||||
      var expectedProgram = [
 | 
					      var expectedProgram = [
 | 
				
			||||||
        ['push', number]
 | 
					        ['push'], [number]
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      expect(program).toMatchArray(expectedProgram);
 | 
					      expect(program).toMatchArray(expectedProgram);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it('parses operators', function() {
 | 
					    it('parses operators', function() {
 | 
				
			||||||
      var program = parse('{ sub }');
 | 
					      var program = parse('{ sub }');
 | 
				
			||||||
      var expectedProgram = [
 | 
					      var expectedProgram = [
 | 
				
			||||||
        ['sub']
 | 
					        ['sub'], [null]
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      expect(program).toMatchArray(expectedProgram);
 | 
					      expect(program).toMatchArray(expectedProgram);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it('parses if statements', function() {
 | 
					    it('parses if statements', function() {
 | 
				
			||||||
      var program = parse('{ { 99 } if }');
 | 
					      var program = parse('{ { 99 } if }');
 | 
				
			||||||
      var expectedProgram = [
 | 
					      var expectedProgram = [
 | 
				
			||||||
        ['jz', 2],
 | 
					        ['jz', 'push'], [2, 99]
 | 
				
			||||||
        ['push', 99]
 | 
					 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      expect(program).toMatchArray(expectedProgram);
 | 
					      expect(program).toMatchArray(expectedProgram);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it('parses ifelse statements', function() {
 | 
					    it('parses ifelse statements', function() {
 | 
				
			||||||
      var program = parse('{ { 99 } { 44 } ifelse }');
 | 
					      var program = parse('{ { 99 } { 44 } ifelse }');
 | 
				
			||||||
      var expectedProgram = [
 | 
					      var expectedProgram = [
 | 
				
			||||||
        ['jz', 3],
 | 
					        ['jz', 'push', 'j', 'push'], [3, 99, 4, 44]
 | 
				
			||||||
        ['push', 99],
 | 
					 | 
				
			||||||
        ['j', 4],
 | 
					 | 
				
			||||||
        ['push', 44]
 | 
					 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      expect(program).toMatchArray(expectedProgram);
 | 
					      expect(program).toMatchArray(expectedProgram);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@ -100,7 +96,7 @@ describe('function', function() {
 | 
				
			|||||||
      var stream = new StringStream(program);
 | 
					      var stream = new StringStream(program);
 | 
				
			||||||
      var parser = new PostScriptParser(new PostScriptLexer(stream));
 | 
					      var parser = new PostScriptParser(new PostScriptLexer(stream));
 | 
				
			||||||
      var code = parser.parse();
 | 
					      var code = parser.parse();
 | 
				
			||||||
      var evaluator = new PostScriptEvaluator(code);
 | 
					      var evaluator = new PostScriptEvaluator(code[0], code[1]);
 | 
				
			||||||
      var output = evaluator.execute();
 | 
					      var output = evaluator.execute();
 | 
				
			||||||
      return output;
 | 
					      return output;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user