All files / resolver/resolvers literalResolver.js

0% Statements 0/27
0% Branches 0/23
0% Functions 0/3
0% Lines 0/26
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105                                                                                                                                                                                                                 
import ConstraintType from '../constraintType';
import TypeConstraint from '../typeConstraint';
import TypeResolver from '../typeResolver';
 
// import STL from '../../stl/stl';
 
import VSLTokenType from '../../parser/vsltokentype.js';
 
/**
 * Resolves any atomic literal described by an `Literal` token class.
 */
export default class LiteralResolver extends TypeResolver {
    
    /**
     * @param {Node} node - The node to resolve.
     * @param {function(from: Node): TypeResolver} getChild - Takes a node and
     *     returns the resolver to execute, it is reccomended to just use a
     *     `switch` statement with `from.constructor` and then use that. It is
     *     fine to throw if the node is unhandled.
     */
    constructor(
        node: Node,
        getChild: (Node) => TypeResolver
    ) {
        super(node, getChild);
    }
    
    /**
     * Resolves types for a given node.
     * 
     * @param {function(offer: ConstraintType): ?TypeConstraint} negotiate - The
     *     function which will handle or reject all negotiation requests. Use
     *     `{ nil }` to reject all offers (bad idea though).
     */
 
    resolve(negotiate: (ConstraintType) => ?TypeConstraint): void {
        // Get context
        const context = negotiate(ConstraintType.TransformationContext).primitives;
 
        // Check the requested types of this ID
        const response = negotiate(ConstraintType.RequestedTypeResolutionConstraint);
 
        // Check if this has a specific type
        const requiredResolution = negotiate(ConstraintType.ContextParentConstraint)
 
        // Specify default types for the candidates
        // Perhaps in the future a STL item would have to register or request
        // to be a default candidate but for now they are hardcoded here
        switch (this.node.type) {
            case VSLTokenType.Integer:
                this.node.typeCandidates = context.get("Integer") || [];
                break;
                
            case VSLTokenType.Decimal:
                this.node.typeCandidates = context.get("FloatingPoint") || [];
                break;
                
            case VSLTokenType.String:
                this.node.typeCandidates = context.get("String") || [];
                break;
                
            case VSLTokenType.Regex:
                this.node.typeCandidates = context.get("Regex") || [];
                break;
                
            default: throw new TypeError(`Undeducatble literal of type ${this.node.type}`);
        }
        
        if (response !== null) {
            this.node.typeCandidates = this.node.typeCandidates.filter(::response.includes)
        }
 
        if (requiredResolution !== null) {
            let res = this.node.typeCandidates.find(candidate => candidate.scopeRef.equal(requiredResolution));
            if (!res) {
                this.emit(
                    `This literal here needs to resolve to something that it ` +
                    `did not resolve to. This error message should probably ` +
                    `be made better.`
                );
            } else {
                this.node.typeCandidates = [res.scopeRef];
                this.node.exprType = res.scopeRef;
            }
        }
        
        if (this.node.typeCandidates.length === 0) {
            this.emit(
                `Literal has no overlapping type candidates. ` + 
                `They are a few reasons this could happen: \n` + 
                `  1. The STL is not linked\n` +
                `  2. You are using a literal which doesn't have a class ` +
                `associated with it.\n` +
                `This is likely an internal bug, but check for an existing` +
                ` report before leaving your own. You can also try to define ` +
                `your own candidate using \`@primitive(...)\``
            );
        }
        
        if (this.node.typeCandidates.length === 1) {
            this.node.exprType = this.node.typeCandidates[0];
        }
    }
}