Question

I am trying to convert this Java interpreter I wrote for my compiler to a Smalltalk interpreter. Is it possible? If so, what would be a good resources to look at? I am completely new to Smalltalk, looks weird to me for now. I would appreciate any help, thanks. Some more info on the program: The input would be an intermediate code file a sample of which is as below.

Intermediate code file, which computes the factorial of a number:

read
store x
push x
store i
push   1.0
store fact
push i
push   1.0
greater
testfgoto 21
push fact
push i
multiply
store fact
push i
push   1.0
minus
store i
push 1.0
testtgoto 7
push fact
print
end

JavaExecutor.java Program :

public void executor(){
    String operation = null;
    StringTokenizer tokens = null;
    String key,value = null;
    Double tempVar = null;
    // Traverse the Arraylist to get the operations
    for(int i=0; i < operations.size(); i++){
        operation = (String)operations.get(i);
        System.out.println("Operation -------"+ operation);
        tokens = new StringTokenizer(operation);
        while(tokens.hasMoreTokens()){
            key = tokens.nextToken();
            //System.out.println("KEY "+ key);
            if(key.toUpperCase().equals("PUSH")){
                //System.out.println("Push Operation");
                value = (String)tokens.nextToken();
                //System.out.println("value "+ value);
                if(checkforVaribaleName(value)){
                    stack.push((Double)assignments.get(value));
                    System.out.println("PUSH"+ (Double)assignments.get(value));
                }
                else if(value != null){
                    stack.push(Double.parseDouble(value));
                    System.out.println("PUSH" + value);
                } else{
                    stack.push(0.0);
                    System.out.println("PUSH" + 0.0);
                }
                break;

            }else if(key.toUpperCase().equals("POP")){
                //NO LOGIC
                break;

            }else if(key.toUpperCase().equals("READ")){
                //System.out.println("Read Operation");
                tempVar = readDoubleFromConsole();
                stack.push(tempVar);
                System.out.println("PUSHP :"+tempVar);
                break;

            }else if(key.toUpperCase().equals("WRITE")){
                break;
            }else if(key.toUpperCase().equals("MULTIPLY")){
                //System.out.println("MULTIPLY operation");
                Double first = (Double)stack.pop();
                Double second = (Double)stack.pop();
                stack.push(first*second);
                System.out.println("PUSH "+ first*second);
                break;

            }else if(key.toUpperCase().equals("DIVIDE")){
                Double first = (Double)stack.pop();
                Double second = (Double)stack.pop();
                stack.push(second/first);
                break;
            }else if(key.toUpperCase().equals("PLUS")){
                Double first = (Double)stack.pop();
                Double second = (Double)stack.pop();
                stack.push(second+first);
                break;
            }else if(key.toUpperCase().equals("MINUS")){
                Double first = (Double)stack.pop();
                Double second = (Double)stack.pop();
                stack.push(second-first);
                System.out.println("PUSH "+ (second-first));
                break;
            }else if(key.toUpperCase().equals("GREATER")){
                //System.out.println("GREATER operation");
                Double first = (Double)stack.pop();
                System.out.println("POP :"+first);
                Double second = (Double)stack.pop();
                System.out.println("POP "+ second);
                if(second>first){
                    stack.push(1.0);
                }
                else{
                    stack.push(0.0);
                }
                break;
            }else if(key.toUpperCase().equals("LESS")){
                Double first = (Double)stack.pop();
                Double second = (Double)stack.pop();
                if(second<first){
                    stack.push(1.0);
                }
                else{
                    stack.push(0.0);
                }
                break;
            }else if(key.toUpperCase().equals("EQUAL")){
                Double first = (Double)stack.pop();
                Double second = (Double)stack.pop();
                if(second==first){
                    stack.push(1.0);
                }
                else{
                    stack.push(0.0);
                }
                break;
            }else if(key.toUpperCase().equals("STORE")){
                //System.out.println("Store operation");
                value = (String)tokens.nextToken();

                assignments.put(value, (Double)stack.pop());
                System.out.println("POP :"+assignments.get(value));
                break;
            }else if(key.toUpperCase().equals("TESTFGOTO")){
                value = (String)tokens.nextToken();
                if((Double)stack.pop() == 0.0){
                    System.out.println("POP " +0.0);
                    i = Integer.parseInt(value)-2;
                }
                break;
            }else if(key.toUpperCase().equals("TESTTGOTO")){
                value = (String)tokens.nextToken();
                if((Double)stack.pop() == 1.0){
                    System.out.println("POP " +1.0);
                    i = (Integer.parseInt(value)-2);
                    System.out.println(i);
                }
                break;
            }else if(key.toUpperCase().equals("PRINT")){
                //System.out.println("PRINT operation");
                System.out.println("Result "+stack.pop());
                break;
            }else if(key.toUpperCase().equals("END")){
                System.out.println("Execution Completed");
                System.exit(0);
            }

        }
    }
}


public static void main(String args[])
{
    String fileName = null;
    if(args.length > 0)
    {
        fileName = args[0];
    }
    else{
        System.out.println("Usage : JavaExecutor fileName.inp");
        System.exit(0);
    }
    JavaExecutor j = new JavaExecutor(fileName);
    j.readFromFile();
    j.executor();


}

}

Was it helpful?

Solution

Here's a VisualWorks Smalltalk version of the interpreter:

'From VisualWorks, 7.8 of March 30, 2011 on May 1, 2012 at 9:47:31 PM'!


CodeComponent create: #package named: 'IntermediateInterpreter'!"Package IntermediateInterpreter*"!


CodeComponent create: #package named: 'IntermediateInterpreter'!

Smalltalk defineClass: #IntermediateInterpreter
    superclass: #{Core.Object}
    indexedType: #none
    private: false
    instanceVariableNames: 'lines currentLineNumber variables stack commands '
    classInstanceVariableNames: ''
    imports: ''
    category: ''!

!IntermediateInterpreter class methodsFor: 'instance creation'!

new
    ^super new initialize
! !


!IntermediateInterpreter methodsFor: 'initialize-release'!

initialize

    stack := OrderedCollection new.
    variables := Dictionary new.
    lines := OrderedCollection new.
    self initializeCommands
!

initializeCommands

    commands := Dictionary new.
    commands
        at: 'READ' put: [:values | stack add: (self tokenize: (Dialog request: 'value?' initialAnswer: ''))];
        at: 'STORE' put: [:values | variables at: values second put: stack removeLast];
        at: 'PUSH' put: [:values | stack add: ((self isVariableName: values second) ifTrue: [variables at: values second] ifFalse: [values second])];
        at: 'GREATER' put: [:values | | a b | b := stack removeLast. a := stack removeLast. stack add: (a > b ifTrue: [1.0] ifFalse: [0.0])];
        at: 'MULTIPLY' put: [:values | | a b | b := stack removeLast. a := stack removeLast. stack add: a * b ];
        at: 'MINUS' put: [:values | | a b | b := stack removeLast. a := stack removeLast. stack add: a - b ];
        at: 'TESTFGOTO' put: [:values | (stack removeLast - 0.0) abs < 0.01 ifTrue: [currentLineNumber := values second]];
        at: 'TESTTGOTO' put: [:values | (stack removeLast - 1.0) abs < 0.01 ifTrue: [currentLineNumber := values second]];
        at: 'PRINT' put: [:values | Transcript show: stack removeLast printString; cr];
        at: 'END' put: [:values | currentLineNumber := 0]! !

!IntermediateInterpreter methodsFor: 'testing'!

isVariableName: aString

    (aString isKindOf: String) ifFalse: [^false].
    ^aString first isAlphabetic! !

!IntermediateInterpreter methodsFor: 'interpreting'!

interpret: aString

    self createLinesFrom: aString.
    currentLineNumber := 1.
    self interpret!

interpret

    | tokens |
    [currentLineNumber = 0] whileFalse: 
            [tokens := lines at: currentLineNumber.
            Transcript show: tokens printString; cr.
            currentLineNumber := currentLineNumber + 1.
            (commands at: tokens first asUppercase
                ifAbsent: [self error: 'Unknown command']) value: tokens]!

tokenizeLine: aString

    ^(((aString tokensBasedOn: Character space)
        reject: [:each | each isEmpty]) collect: [:each | self tokenize: each]) asArray!

tokenizeCurrentLine

    ^(((lines at: currentLineNumber) tokensBasedOn: Character space)
        reject: [:each | each isEmpty]) collect: [:each | self tokenize: each]!

createLinesFrom: aString

    | stream |
    stream := aString readStream.
    [stream atEnd] whileFalse: [lines add: (self tokenizeLine: (stream upTo: Character cr))]!

tokenize: each

    ^(self isVariableName: each)
        ifTrue: [each]
        ifFalse: [Number readFrom: each readStream]! !

OTHER TIPS

It should not be to hard at all to implement interpreter for your intermediate code in Smalltalk, but you need to know at least basics of Smalltalk: Collection classes, Stream classes, and making yourself comfortable in IDE.

Stephane Ducasse has great collection of free Smalltalk books

Automated translation between programming languages is possible in theory, feasible only in a small number of circumstances, efficient in very few of those. Even automated translation of virtual machine bytecode is usually not efficient (and the JVM is rather Java-specific; translating to/from Smalltalk bytecode may not go well).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top