tom-weatherhead/thaw-grammar

View on GitHub
src/languages/smalltalk/domain-object-model/object-instance.ts

Summary

Maintainability
B
4 hrs
Test Coverage
// tom-weatherhead/thaw-grammar/src/languages/smalltalk/domain-object-model/object-instance.ts

// **** BEGIN Bootstrapping Code Part 2 ****

import { Name } from 'thaw-interpreter-core';

import { BeginUsage } from '../../../common/domain-object-model/begin-usage';

import { EnvironmentFrame } from '../../../common/domain-object-model/environment-frame';

import { FunctionDefinition } from '../../../common/domain-object-model/function-definition';

import { ISmalltalkValue } from './interfaces/iexpression';

import { SmalltalkInteger } from './data-types/integer';

import { SmalltalkString } from './data-types/string';

import { SmalltalkUserValue } from './data-types/user-value';

// import { SmalltalkBeginUsage } from './begin-usage';

import { falseVar, objectClass, objectClassName, selfVar, trueVar } from './bootstrap';

import { SmalltalkClass } from './class';

// import { SmalltalkEnvironmentFrame } from './environment-frame';

// import { SmalltalkFunctionDefinition } from './function-definition';

import { SmalltalkSetUsage } from './set-usage';

import { SmalltalkVariable } from './variable';

// Create objectInstance

const objectInstanceEnvFrame = new EnvironmentFrame<ISmalltalkValue>();
export const defaultValue = new SmalltalkInteger(0);

objectInstanceEnvFrame.add(selfVar, defaultValue);

export const objectInstance = new SmalltalkUserValue(objectClass, objectInstanceEnvFrame);

// Tie the self-referential knot:
objectInstance.value.dict.set(selfVar.name, objectInstance);

// true and false: Version 1:

export const falseValue = new SmalltalkInteger(0);
export const trueValue = new SmalltalkInteger(1);

// true and false: Version 2:

// We want true and false to be functions, as in the Lambda calculus:

// (true x y) -> x
// (false x y) -> y

// ... but evaluate x and y lazily; e.g. in the case of 'true', do not evaluate y.

// const x = new SmalltalkVariable('x');
// const y = new SmalltalkVariable('y');
//
// // Note: This will not work; a function definition is not a value. We need closures...
// // Or use Blocks, and unblock only one of the two parameters.
// // E.g. in the case of 'true', unblock x but not y.
// export const falseValue = new SmalltalkFunctionDefinition(falseVariableName, [x, y], y);
// export const trueValue = new SmalltalkFunctionDefinition(trueVariableName, [x, y], x);

// From the C# version:

// Evaluate(string.Format(@"
// (class {0} Object ()
// (stringValue) ; stringValue is used as the value of the object of this class when it is converted to a string.
// (define init () (begin (set stringValue '{1}') self))
// (define if (trueBlock falseBlock) falseBlock)
// (define and (x) {2})
// (define or (x) x)
// (define xor (x) x)
// (define not () {3})
// )", FalseValueClassName, FalseValueAsString, FalseVariableName, TrueVariableName));
// Evaluate(string.Format(@"
// (class {0} Object ()
// (stringValue) ; stringValue is used as the value of the object of this class when it is converted to a string.
// (define init () (begin (set stringValue '{1}') self))
// (define if (trueBlock falseBlock) trueBlock)
// (define and (x) x)
// (define or (x) {2})
// (define xor (x) (not x))
// (define not () {3})
// )", TrueValueClassName, TrueValueAsString, TrueVariableName, FalseVariableName));
// Evaluate(string.Format("(set {0} (init (new {1})))", FalseVariableName, FalseValueClassName));
// Evaluate(string.Format("(set {0} (init (new {1})))", TrueVariableName, TrueValueClassName));
// FalseVal = GlobalEnvironment.Dict[new SmalltalkVariable(FalseVariableName)];
// TrueVal = GlobalEnvironment.Dict[new SmalltalkVariable(TrueVariableName)];

const nilClassName = 'Nil';
const nilVariableName = 'nil';
const nilValueAsString = 'nil';

const falseClassName = 'FalseValue';
const falseValueAsString = 'false';

const trueClassName = 'TrueValue';
const trueValueAsString = 'true';

const stringValueVariableName = 'stringValue';

export const nilVar = new SmalltalkVariable(nilVariableName);
const stringValueVar = new SmalltalkVariable(stringValueVariableName);

const x = new SmalltalkVariable('x');
const y = new SmalltalkVariable('y');

export const nilClass = new SmalltalkClass(
    nilClassName,
    objectClassName,
    [],
    [stringValueVar],
    [
        new FunctionDefinition<ISmalltalkValue>(
            new Name('init'),
            [],
            new BeginUsage<ISmalltalkValue>(
                new SmalltalkSetUsage(stringValueVar, new SmalltalkString(nilValueAsString)),
                [selfVar]
            )
        ),
        new FunctionDefinition<ISmalltalkValue>(new Name('isNil'), [], trueVar),
        new FunctionDefinition<ISmalltalkValue>(new Name('notNil'), [], falseVar)
    ]
);

export const falseClass = new SmalltalkClass(
    falseClassName,
    objectClassName,
    [],
    [stringValueVar],
    [
        // (define init () (begin (set stringValue '{1}') self)) :
        new FunctionDefinition<ISmalltalkValue>(
            new Name('init'),
            [],
            new BeginUsage<ISmalltalkValue>(
                new SmalltalkSetUsage(stringValueVar, new SmalltalkString(falseValueAsString)),
                [selfVar]
            )
        ),
        new FunctionDefinition<ISmalltalkValue>(new Name('if'), [x, y], y)
        // ... and, or, xor, not
    ]
);

export const trueClass = new SmalltalkClass(
    trueClassName,
    objectClassName,
    [],
    [stringValueVar],
    [
        // (define init () (begin (set stringValue '{1}') self)) :
        new FunctionDefinition<ISmalltalkValue>(
            new Name('init'),
            [],
            new BeginUsage<ISmalltalkValue>(
                new SmalltalkSetUsage(stringValueVar, new SmalltalkString(trueValueAsString)),
                [selfVar]
            )
        ),
        new FunctionDefinition<ISmalltalkValue>(new Name('if'), [x, y], x)
        // ... and, or, xor, not
    ]
);

// Create nilInstance

const nilInstanceEnvFrame = new EnvironmentFrame<ISmalltalkValue>();

nilInstanceEnvFrame.add(selfVar, defaultValue);

export const nilInstance = new SmalltalkUserValue(nilClass, nilInstanceEnvFrame);

// Tie the self-referential knot:
nilInstance.value.dict.set(selfVar.name, nilInstance);

// Create falseInstance ...

const falseInstanceEnvFrame = new EnvironmentFrame<ISmalltalkValue>();

falseInstanceEnvFrame.add(selfVar, defaultValue);

export const falseInstance = new SmalltalkUserValue(falseClass, falseInstanceEnvFrame);

// Tie the self-referential knot:
falseInstance.value.dict.set(selfVar.name, falseInstance);

// Create trueInstance ...

const trueInstanceEnvFrame = new EnvironmentFrame<ISmalltalkValue>();

trueInstanceEnvFrame.add(selfVar, defaultValue);

export const trueInstance = new SmalltalkUserValue(trueClass, trueInstanceEnvFrame);

// Tie the self-referential knot:
trueInstance.value.dict.set(selfVar.name, trueInstance);

// **** END Bootstrapping Code Part 2 ****