Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

123 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tender

Tender is an experimental programming language specially designed for graphics, image processing, audio, scripting, and more! Here is a quick tutorial. Also check the docs!

Overview

Tender compiles into bytecode and executes on a stack-based virtual machine (VM) written in native Go. The language features a rich type system including matrix types for high-performance numerical computing, concurrency primitives with goroutines and channels, and a comprehensive standard library covering everything from graphics to networking.

Why Tender?

Modern scripting often means installing dozens of packages before drawing a window, loading an image, or making a network request. Tender takes a different approach. It's perfect for building OpenGL (GL, GLUT, GLU, GLFW) prototypes instantly, without hours of build time.

S³ Philosophy

  • Simple — Readable syntax with familiar language features
  • Single Binary — Compile once. Ship a single executable.
  • Self-Sufficient — Graphics, OpenGL, audio, networking, image processing, compression, GUI, and more are included in the standard library.

Features

  • Simple and highly readable syntax
  • Compiles to bytecode
  • Supports rich built-in functions
  • Includes an extensive standard library
  • Designed for 2D graphics
  • REPL (Read-Eval-Print Loop) for interactive development
  • Rich type system including int, float, string, bool, char, null, big integers, big floats, complex numbers, bytes, arrays (dynamic and immutable), maps (dynamic and immutable), tuples, time values, error values, and matrices
  • High-performance matrix types with support for int, float, and complex elements; element-wise and matrix multiplication; transposition; determinant; rank; trace; and diagonal operations
  • Built-in concurrency with goroutines (govm), channels (makechan), and synchronization primitives
  • User-defined structs with field types, nested structs, anonymous structs, and embedded fields
  • Closures and first-class functions
  • Template literals with ${} interpolation (similar to JavaScript template strings)
  • Advanced operators including pipe operators (<|, |>), null coalescing (??), optional chaining (?.), ternary conditional (? :), compound assignment operators, and logical operators (&&, ||)
  • Modular architecture with import statements, module aliasing, selective imports, embedded file import (embed()), and file-based module loading
  • Runtime type introspection with typeof() and type checking functions
  • Error handling through the error() expression
  • Immutable data structures via freeze() builtin
  • Loop control with break and continue statements
  • For loops including traditional, for-in, conditional, and infinite loops
  • Variable declarations with var and constants with const
  • Function definitions with fn keyword
  • Export statements for module exports
  • Bytecode compilation with compilation, execution, and parse-only modes
  • Comprehensive operator precedence matching conventional expectations
  • Cross-platform support for Windows, macOS, Linux and Android (Termux)

Supported Standard Library

  • math: Mathematical constants and functions
  • mathf: Unity-inspired math utilities for game development
  • cmplx: Functions for complex numbers
  • os: Platform-independent interface to OS functionality
  • strings: String conversion, manipulation, and regular expressions
  • times: Time-related functions
  • rand: Random number generation
  • fmt: Formatting functions
  • json: JSON handling functions
  • xml: XML handling functions
  • base64: Base64 encoding and decoding
  • hex: Hexadecimal encoding and decoding
  • console: Functions to print colored text to the terminal
  • gzip: Gzip compression and decompression
  • zip: ZIP archive manipulation
  • tar: TAR archive creation and reading
  • bufio: Buffered I/O functions
  • crypto: Cryptographic functions
  • path: File path manipulation
  • image: Image manipulation
  • canvas: Drawing functions for canvases
  • graphics: 2D graphics with OpenGL acceleration
  • gl: OpenGL bindings for 3D graphics
  • glu: OpenGL Utility Library bindings
  • glut: OpenGL Utility Toolkit bindings
  • glfw: GLFW window and input management
  • dll: Dynamic link library interactions
  • io: Input and output functions
  • audio: Audio processing
  • net: Networking functions
  • http: HTTP client and server utilities
  • websocket: WebSocket communication utilities
  • gob: Gob Encoding/Decoding
  • csv: CSV Encoding/Decoding
  • wui: Native Windows GUI framework
  • sync: Synchronization primitives

Quick Start

  1. Install Tender on your machine.
  2. Copy the sample code below:
// Canvas drawing example
import "canvas"

ctx := canvas.new_context(100, 100)
ctx.hex("#0f0") 
ctx.dash(4, 2)          
ctx.rect(25, 25, 50, 50) 
ctx.stroke()

ctx.save_png("out.png") 
  1. Save your code as hello.td (use the .td extension).
  2. Run your script using the following command:
tender hello.td

Installation

Using Go

  1. Install the latest version of Go.
  2. Run the following command to install:
go install github.com/2dprototype/tender/cli/tender@latest

Manual Installation (Windows)

Precompiled binaries are available. Download them from the release tags.


Documentation

Check the docs!

Examples

Hello, World

println("Hello, World!")

Graphics

import "graphics"

win := graphics.new_window(400, 400, "Tender")

win.on_draw(fn() {
    win.clear("#000")
    win.hex("#f00")
    win.circle(200, 200, 100)
    win.fill()
})

win.run()

OpenGL

import "gl"
import "glut"

glut.init()
gl.init()
glut.init_display_mode(glut.RGBA | glut.DOUBLE | glut.DEPTH)
glut.init_window_size(400, 400)
glut.create_window("Tender OpenGL")

glut.display_func(fn() {
    gl.clear(gl.COLOR_BUFFER_BIT)
    gl.begin(gl.TRIANGLES)
    gl.color3f(1, 0, 0)
    gl.vertex2f(0, 0.8)
    gl.color3f(0, 1, 0)
    gl.vertex2f(-0.8, -0.8)
    gl.color3f(0, 0, 1)
    gl.vertex2f(0.8, -0.8)
    gl.end()
    glut.swap_buffers()
})

glut.main_loop()

Basic Examples

// Variable declarations
var name = "Tender"
const PI = 3.14159

// Functions
fn add(a, b) {
    return a + b
}

// Closures
fn make_counter() {
    var count = 0
    return fn() {
        count++
        return count
    }
}

// Arrays and maps
var arr = [1, 2, 3, 4, 5]
var map = { "key": "value" }

// Template literals
var user = "John"
var greeting = `Hello ${user}, welcome to Tender!`
println(greeting)

// Structs
type Person struct {
    name string
    age  int
}

var person = Person{name: "John", age: 25}
person.age = 26

// Type conversion and checking
var num = int("123")
if is_string(num) {
    println("This is a string")
}
else {
    println("This is not a string")
}

// Error handling
var result = error("something went wrong")
if is_error(result) {
    println(result.value)
}

Advanced Examples

// Pipe operators for functional composition
var result = [1, 2, 3, 4, 6] |> sort |> reverse |> println

// Null coalescing
var value = null ?? "default value"

// Template literals
var items = ["apple", "banana", "orange"]
for item in items {
    `Item: ${item}` |> println
}

// Optional chaining
var user = {
    profile: {
        name: "jack"
    }
}
var name = user?.profile?.name
sysout name, "\n"

// Range generation
var numbers = range(0, 10, 2)  // [0, 2, 4, 6, 8]
sysout numbers, "\n"

// Module imports
import "math" as m
var sqrt2 = m.sqrt(2)
println(sqrt2)

Matrix Operations (New!)

Tender supports high-performance matrix types for numerical computing:

// Create matrices
m1 := matrix([
	[1, 2, 3], 
	[4, 5, 6],
	[4, 5, 6]
])

m2 := matrix([
	[7,  8,  1], 
	[9,  10, 2], 
	[11, 12, 2]
])

// Matrix multiplication
m3 := m1 * m2
debug(m3)

// Element-wise operations
m4 := m1 + 10  // Add scalar to every element
debug(m4)

// Matrix properties
rows := m1.rows
cols := m1.cols
shape := m1.shape
debug(rows, cols, shape)

// Transpose
m1t := m1.T
debug(m1t)

// For square matrices
det := m1.det      // determinant
trace := m1.trace  // trace
diag := m1.diag    // diagonal elements
debug(det, trace, diag)

// Matrix methods
row0 := m1.row(0)   // Get first row as array
col1 := m1.col(1)   // Get second column as array
flat := m1.flatten  // Flatten to array
debug(row0, col1, flat)

// Type conversion
m_int := matrix(3, 3, "int", [1, 2, 3, 4, 5, 6, 7, 8, 9])

m_float := m_int.to_float()      // Convert to float matrix
m_complex := m_int.to_complex()  // Convert to complex matrix
debug(m_float |> typeof, m_complex |> typeof)

Concurrency (New!)

Tender provides built-in goroutines and channels for concurrent programming:

// ----- Simple goroutine -----
g := go fn() {
    println("Hello from goroutine!")
    return 42   // return a value
}()

// Wait for completion (blocks until done)
g.wait()

// Get the return value
result := g.result()
println("Goroutine returned:", result)  // 42

// Abort a goroutine (if needed, e.g., from another goroutine)
// g.abort()

// ----- Channels -----
ch := chan(10)  // buffered channel with capacity 10

// Send and receive
ch <- "hello"
msg := <-ch
println(msg)  // "hello"
ch.close() // Close the channel (sends no more values)

// ----- Concurrent worker pool -----
fn worker(id, jobs, results) {
    for {
        job := <-jobs        // blocks until a value is available
        if is_null(job) {    // channel closed => receive returns null
            break
        }
		results <- job * 2   // send result
    }
}

jobs := chan(100)
results := chan(100)

// Start 10 workers
for i := 0; i < 10; i++ {
    // govm(worker, i, jobs, results
	go worker(i, jobs, results)
}

// Send 50 jobs
for i := 0; i < 50; i++ {
    jobs <- i
}
jobs.close()  // signal workers to stop

// Collect results (order may vary)
for i := 0; i < 50; i++ {
    res := <-results
    println(res)
}

Explore various examples demonstrating Tender's features in the examples directory.


Command Line Usage

Tender supports multiple operation modes:

# Start REPL (interactive mode)
tender

# Compile and run a source file
tender myapp.td

# Compile to bytecode
tender -o myapp myapp.td

# Run compiled bytecode
tender myapp

# Parse and output AST as JSON
tender -parse ast.json myapp.td

# Show version
tender -version
# or
tender -v

# Show help
tender -help

Type System Overview

Tender provides a rich type system with support for:

Type Description Example
int 64-bit integer 42
float 64-bit floating point 3.14159
bigint Arbitrary-precision integer bigint(12345678...)
bigfloat Arbitrary-precision float bigfloat(3.1415...)
complex Complex number 3+4i
string UTF-8 string "hello"
bool Boolean true or false
char Unicode character 'a'
bytes Byte array [72, 101, 108, 108, 111]
array Dynamic array [1, 2, 3]
immutable-array Immutable array [1, 2, 3]
map Dynamic map {"key": value}
immutable-map Immutable map {"key": value}
tuple Fixed-size immutable sequence (1, "hello", true)
matrix:int Integer matrix matrix(1,2,"int",[1,2])
matrix:float Float matrix matrix(1,2,"float",[1,2.2])
matrix:complex Complex matrix matrix(1,2,"complex",[1,2i])
struct User-defined structure user{name: "Alice", age: 30}
time Time value time()
error Error value error("message")
null Null value null
channel Communication channel chan(10)
goroutine Concurrent task handle go fn(){ ... }()

Dependencies

Syntax Highlighting

Syntax highlighting is currently available for:

  • Notepad++: Download the configuration file here
  • Support for additional editors coming soon

License

Tender is distributed under the MIT License, with additional licenses provided for third-party dependencies. See LICENSE_GOLANG and LICENSE_TENGO for more information.


Acknowledgments

Tender is written in Go, based on Tengo. We extend our gratitude to the contributors of Tengo for their valuable work.

About

Scripting language designed for special tasks

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages