Skip to content

Basic Syntax

This guide covers the fundamental syntax elements of the Onion programming language.

Comments

Currently, Onion supports C-style comments:

// Single-line comment

/*
 * Multi-line comment
 * Spans multiple lines
 */

Variables

Variable Declaration

Variables are declared with val (immutable) or var (mutable). Local declarations can omit the type when an initializer is present; otherwise provide an explicit type:

val name = "Alice"
var count = 0
val age: Int = 30
val price: Double = 19.99
val isActive: Boolean = true

Assignments update existing variables; they do not declare new ones.

Naming Conventions

  • Variable names use camelCase: firstName, totalCount
  • Class names use PascalCase: Person, Calculator
  • Fields are accessed via this.field

Primitive Types

Onion supports the standard JVM primitive types:

Type Description Example
Int 32-bit integer 42
Long 64-bit integer 42L
Double 64-bit floating point 3.14
Float 32-bit floating point 3.14f
Boolean true or false true, false
Char Single character 'A'
Byte 8-bit integer 127
Short 16-bit integer 1000

Literals

String Literals

val greeting: String = "Hello, World!"
val multiline: String = "Line 1\nLine 2\nLine 3"
val withQuotes: String = "She said \"Hello\""

Numeric Literals

val decimal: Int = 42
val hex: Int = 0xFF
val binary: Int = 0b1010
val octal: Int = 077
val longValue: Long = 100L
val byteValue: Byte = 5B
val shortValue: Short = 5S
val doubleValue: Double = 3.14
val floatValue: Float = 3.14f
val scientific: Double = 1.23e10

Underscores group digits in any numeric literal:

val million = 1_000_000
val mask = 0xFF_FF
val flags = 0b1010_1010
val precise = 1_234.5

Character Literals

val letter: Char = 'A'
val newline: Char = '\n'
val tab: Char = '\t'

Boolean Literals

val isTrue: Boolean = true
val isFalse: Boolean = false

Null Literal

val nullable: String? = null   // null needs a nullable type (W0012 otherwise)

Operators

Arithmetic Operators

val a: Int = 10
val b: Int = 3

val sum: Int = a + b        // 13
val diff: Int = a - b       // 7
val product: Int = a * b    // 30
val quotient: Int = a / b   // 3
val remainder: Int = a % b  // 1

Comparison Operators

val x: Int = 5
val y: Int = 10

x == y  // false (equal)
x != y  // true  (not equal)
x < y   // true  (less than)
x > y   // false (greater than)
x <= y  // true  (less than or equal)
x >= y  // false (greater than or equal)

Logical Operators

val a: Boolean = true
val b: Boolean = false

a && b  // false (logical AND)
a || b  // true  (logical OR)
!a      // false (logical NOT)

Assignment Operators

var x: Int = 10

x = 20       // Simple assignment
x = x + 5    // Add and assign (no += syntax yet)
x = x - 3    // Subtract and assign
x = x * 2    // Multiply and assign

Increment/Decrement

var count: Int = 0
count = count + 1  // Increment
// Or use post-increment (in some contexts)
count++
count--

Type Casting Operator

The as keyword performs type casting. When chaining with method calls, use parentheses:

val x: Double = 3.14
val y: Int = x as Int  // Cast to Int (3)

val random: Double = Math::random()
val randomInt: Int = (random * 100) as Int

// When chaining method calls, parentheses are required
val btn: Object = getButton()
val text: String = (btn as JButton).getText()

List Append Operator

The << operator appends to lists:

import { java.util.ArrayList; }

val list: ArrayList[String] = new ArrayList[String]()
list << "First"
list << "Second"
list << "Third"

Arrays

Array Declaration

// Create array with size
val numbers: Int[] = new Int[10]

// Initialize elements
val colors: String[] = new String[3]
colors[0] = "red"
colors[1] = "green"
colors[2] = "blue"

val scores: Double[] = new Double[5]
scores[0] = 95.5
scores[1] = 87.3

Array Access

val fruits: String[] = new String[3]
fruits[0] = "apple"
fruits[1] = "banana"
fruits[2] = "orange"

val first: String = fruits[0]     // "apple"
val second: String = fruits[1]    // "banana"

fruits[2] = "grape"  // Modify element

val length: Int = fruits.length  // Array length

Expressions

Arithmetic Expressions

val result: Int = (10 + 5) * 2 - 3  // 27
val average: Double = (10 + 20 + 30) / 3.0

String Concatenation

val firstName: String = "Alice"
val lastName: String = "Smith"
val fullName: String = firstName + " " + lastName

val age: Int = 30
val message: String = "I am " + age + " years old"

Method Calls

// Static method call
println("Hello")

// Instance method call
val text: String = "hello"
val upper: String = text.toUpperCase()
val len: Int = text.length

Object Creation

import { java.util.ArrayList; }

val list: ArrayList[String] = new ArrayList[String]()
val array: String[] = new String[10]

Block Elements

Expressions In Blocks

Any expression can appear directly inside a block:

println("Hello")
var x: Int = 10
x = x + 1

Block Expressions

Blocks are enclosed in curly braces:

{
  val temp: Int = 5
  println(temp)
  // temp is only visible in this block
}

Scope and Visibility

Local Variables

Variables declared in a method or block are local to that scope:

def method {
  val local: Int = 10
  // local is only visible here
}

Fields

Fields are declared with val / var and accessed via this.field:

class Example {
  var count: Int
  val name: String = "default"

  public:
    def increment {
      this.count = this.count + 1
    }
}

Access Modifiers

By default, members are private. Use public: to mark public members:

class Person {
  val ssn: String = "000-00-0000"  // Private by default

  public:
    val name: String = "Alice"  // Public

    def getName: String = this.name  // Public method
}

Interfaces

An interface declares method signatures without bodies. A whole interface can sit on a single line, and a no-body method may be followed by the closing } on the same line:

interface Shape { def area(): Double }

class Circle : Object <: Shape {
  val r: Double
public:
  def this(r: Double) { this.r = r }
  override def area(): Double = 3.14 * this.r * this.r
}

val s: Shape = new Circle(2.0)
println(s.area())   // 12.56

Module System

Import Statements

Import Java classes for use in your Onion code:

import {
  java.util.ArrayList;
  java.util.HashMap;
  java.io.File;
}

val list: ArrayList[String] = new ArrayList[String]()
val map: HashMap[String, String] = new HashMap[String, String]()
val file: File = new File("data.txt")

Fully Qualified Names

You can also use fully qualified names without importing:

val list: java.util.ArrayList[String] = new java.util.ArrayList[String]()

Next Steps