Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: Logic

Logic

Expressions and operators

Precedence Operators Operands Result
1 (tightest) not, unary - Bool; a number same
2 *, /, % * and % may mix named types; / needs the same named type: Int drops the remainder, Decimal is exact Int, or Decimal if either side is Decimal
3 +, - the same named type after widening, or a literal; + also joins two Text values as above
4 <, <=, >, >= two numbers or two time values of the same named type; text has no order Bool
5 ==, != two values of the same type after widening, or a nullable value and none Bool
6 and Bool Bool
7 (loosest) or Bool Bool

"Widening" is one type standing in for another it is built on (When one type can stand in for another).

Adding two values needs the same type on each side, and multiplying may mix them, because multiplying a price by a quantity means something and adding them doesn't:

example
var wrong: Stock = Stock(per_pack + packs)var line: Stock = Stock(per_pack * packs)var earlier: Bool = name < other_namevar share: ItemPrice = decimal.divide(total, people, rounding: Rounding.half_even)var boxes: BoxCount = integer.divide(items, box_size, rounding: Rounding.up)
  • per_pack + packs is an error: it adds a Quantity to a Stock.
  • per_pack * packs is fine: it multiplies different units.
  • name < other_name is an error: text has no order, because the order depends on the language. Sort text with list.sort_by and a text key.
  • decimal.divide and integer.divide divide values of different types, or round another way, with the rounding you name.
  • box_size's type excludes zero. A divisor's type must, so dividing by zero is ruled out while compiling (type.divisor_zero).

In +, - and /, a literal takes the other side's type, exactly as it does in ==. So price + 3 with a Decimal price is an error, as price == 3 is: write 3.00. + joins two Text values only when they are the same named type after widening, or one is a literal, as == compares them. * and % still mix.

Operators work on the built-in type a named type is built on, so the result is a plain Int, Decimal, Text or Bool. To turn it back into a named type, construct it: Stock(total + holdback) (Creating values). Brackets group. and and or stop as soon as the answer is known. a < b < c is an error, because a < b is a Bool.

Logical operators are words. !, && and || are not Jadpo, and each is one error whose edit writes the word (syntax.logical_operator). Nor are === and !==: == and != already compare values of one type, so each is one error whose edit writes == or != (syntax.equality_operator). So are SQL's <>, = and IS NULL (Habits from other languages).

Operators on standard types, such as price * 20% or distance / 2h, follow the standard operator table. Anything in neither that table nor the one above is a compile error naming the two types. 20% is a Percentage literal. The remainder operator keeps % with spaces round it, as the formatter writes every binary operator, and 20%3 is syntax.percent_ambiguous, naming both readings. Rounding.down rounds toward zero (Numbers).

Markdown for agents: /docs/expressions-and-operators.md.Built from Jadpo main at a707efb.