Skip to content

Brain-dawg/TypeSquirrel

 
 

Repository files navigation

TypeSquirrel

A static type analyzer for the Squirrel programming language. Catch type errors when debugging!

This is an extremely unfinished side project in the proof-of-concept stages, there are obvious problems with the linter/analyzer, awkward unfinished glue code all over the place, etc. Making this public because I don't know when I'll pick it up again and I'd rather not leave it bit-rotting.

This is/was mostly an experiment to see how useful optional type checking would be in VScript, similar to MyPy. The short answer is it's very useful, but the concerns of a bifurcated ecosystem that depends on a specialized third-party tool to strip the type annotations means this project is temporarily shelved. This idea would be better off as something that is still fully vanilla squirrel compatible using inline comments, and a custom linter/highlighter to pretty-print them in-editor, rather than the nuclear approach this idea is going for.

Type Annotation Syntax

Variable Declarations

local name: string   = "John";
local age: int       = 25;
local height: float  = 5.9;
local isActive: bool = true;
local data: any      = null;

Array Types

local numbers: array<int> = [1, 2, 3];
local names: string[] = ["Alice", "Bob"];

Function Types

// Function declaration
function greet(name: string, age: int): string {
    return "Hello " + name + ", age " + age;
}

Table Types

local person: {name: string, age: int} = {
    name = "John",
    age = 30
};

Union and Optional Types

local value: int | string = "could be either";
local optional: string? = null; // Equivalent to string | null

Class Types

class Person {
    name: string;
    age: int;
    
    constructor(name: string, age: int) {
        this.name = name;
        this.age = age;
    }
    
    function getName(): string {
        return this.name;
    }
}

Error Categories

  • Type Mismatch: Assignment of incompatible types
  • Undefined Variable: Reference to undeclared variables
  • Invalid Member Access: Access to non-existent table members
  • Null Pointer: Use of potentially null values without checks

Examples

See the examples/ directory for sample Squirrel/VScript files with type annotations:

  • basic_types.nut: Demonstrates various type annotation syntaxes
  • type_errors.nut: Examples of common type errors for testing

Standalone Analyzer Usage

This doesn't actually do any type checking, currently unfinished

Requires python 3.10+. winget install python in cmd/powershell if you don't have it.

git clone https://github.com/Brain-dawg/TypeSquirrel
cd squirrel-analyzer
pip install -r requirements.txt
python generate_parser.py

Commands

# Type check a file ( UNFINISHED )
python squirrel_analyzer.py script.tnut

# Type check and strip annotations ( UNFINISHED )
python squirrel_analyzer.py -c -s script.tnut

# Strip type annotations only
python squirrel_analyzer.py -s -o script.nut script.tnut

# JSON output
python squirrel_analyzer.py -fmt json script.tnut

Python API

from squirrel_analyzer import SquirrelAnalyzer

analyzer = SquirrelAnalyzer()

# Analyze a file
result = analyzer.analyze_file("script.nut", check_types=True, strip_annotations=True)

# Analyze source code string
result = analyzer.analyze_string(source_code, check_types=True, strip_annotations=True)

# Access results
if result["success"]:
    for message in result["messages"]:
        print(f"{message.location}: {message.severity.value}: {message.message}")
    
    if result["stripped_code"]:
        print("Stripped code:", result["stripped_code"])

Ways to improve this

  • Type inference.
  • Entities should be inherently nullable, with an ! operator to tell the analyzer otherwise (C# style). The only exception to this is worldspawn, which can never be null without the engine crashing.
  • netprop and native function argument type errors. Started but not working atm.
  • entity class names instead of just a generic "entity" type (CTFPlayer, CTriggerOnce, etc.)
  • Newslot operators don't work (foo: string <- "bar"), analyzer is bad and thinks this is part of a ternary.
  • Error checking on class members is limited or nonexistent. This may be the case with tables too?

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 52.9%
  • TypeScript 40.9%
  • Squirrel 4.3%
  • ANTLR 1.5%
  • Other 0.4%