1
0
Fork
You've already forked comath
0
forked from InKryption/comath
No description
  • Zig 100%
ssteinbach 502c5e65c3 Use @alignOf to compute alignment
* alignment = 0 is no longer the way to signal default alignment
2025年09月08日 18:26:57 +02:00
src Use @alignOf to compute alignment 2025年09月08日 18:26:57 +02:00
.gitignore Update .gitignore 2024年07月25日 15:35:02 +02:00
build.zig Update to zig master 2025年07月23日 13:33:01 +02:00
build.zig.zon build manifest: bump versions 2025年07月09日 05:59:38 +02:00
LICENSE Add LICENSE (MIT) 2023年08月23日 12:12:28 +00:00
README.md Remove allow_unused_inputs, add evalWithUnused 2025年06月08日 20:20:51 +02:00

comath: comptime math

The main function this library provides is eval, which is of the form

fneval(comptimeexpr:[]constu8,ctx:anytype,inputs:anytype,)!Eval(expr,@TypeOf(ctx),@TypeOf(inputs))

wherein the expr is expected to be source code representing an expression comprised of:

  • Identifiers, whose value should be assigned by a field in inputs of the same name, or be defined by the ctx.
  • Integer, float, or character literals
  • Grouped expressions delimited by parentheses
  • Field accesses (expression.identifier|operator symbols)
  • Index accesses (expression[expressions])
  • Function calls (expression(expressions))
  • Unary operations (operator expression)
  • Binary operations (expression operator expression)

Given an expression that is successfully parsed into an AST at comptime, said AST will then be evaluated. The semantics of all the operations are defined by the ctx parameter, which should be a type that conforms to a concrete interface, which can be described in pseudo-code as:

{/// Should return `true` for any string of symbols corresponding to a recognized unary operator.pubinlinefnmatchUnOp(comptimestr:[]constu8)bool{...}/// Should return `true` for any string of symbols corresponding to a recognized binary operator.pubinlinefnmatchBinOp(comptimestr:[]constu8)bool{...}/// Returns the order of the binary operators `lhs` and `rhs`, where `matchBinOp(lhs) = true`, and/// `matchBinOp(rhs) = true`.pubinlinefnorderBinOp(comptimelhs:[]constu8,comptimerhs:[]constu8)?Order{...}/// Determines the value and type of number literals.pubfnEvalNumberLiteral(comptimesrc:[]constu8)type{...}pubfnevalNumberLiteral(comptimesrc:[]constu8)EvalNumberLiteral(src){...}/// Determines the value and type of identifiers, overriding those which would otherwise be/// determined via the `inputs` struct. `EvalIdent` returning `noreturn` causes/// `eval` to instead look for the identifier in the `inputs` struct.pubfnEvalIdent(comptimeident:[]constu8)type{...}pubfnevalIdent(ctx:@This(),comptimeident:[]constu8)!EvalIdent(ident){...}/// Corresponds to `lhs.accessor`.pubfnEvalProperty(comptimeLhs:type,comptimeaccessor:[]constu8)type{...}pubfnevalProperty(ctx:@This(),lhs:anytype,comptimeaccessor:[]constu8)!EvalProperty(@TypeOf(lhs),accessor){...}/// Corresponds to `lhs[rhs...]`, where `rhs` is a tuple whose elements are the list of indices used to access `lhs`.pubfnEvalIndexAccess(comptimeLhs:type,comptimeRhs:type)type{...}pubfnevalIndexAccess(ctx:@This(),lhs:anytype,rhs:anytype)!EvalIndexAccess(@TypeOf(lhs),@TypeOf(rhs)){...}/// Corresponds to `callee(args...)`, where `args` is a tuple whose elements are the arguments to `callee`.pubfnEvalFuncCall(comptimeCallee:type,comptimeArgs:type)type{...}pubfnevalFuncCall(ctx:@This(),callee:anytype,args:anytype)!EvalFuncCall(@TypeOf(callee),@TypeOf(args)){...}/// Corresponds to `op value`./// In most contexts, it should be sufficient to assume `@hasField(UnOp, op)`.pubfnEvalUnOp(comptimeop:[]constu8,comptimeT:type)type{...}pubfnevalUnOp(ctx:@This(),comptimeop:[]constu8,value:anytype)!EvalUnOp(op,@TypeOf(value)){...}/// Corresponds to `lhs op rhs`/// In most contexts, it should be sufficient to assume `@hasField(BinOp, op)`.pubfnEvalBinOp(comptimeLhs:type,comptimeop:[]constu8,comptimeRhs:type)type{...}pubfnevalBinOp(ctx:@This(),lhs:anytype,comptimeop:[]constu8,rhs:anytype)!EvalBinOp(@TypeOf(lhs),op,@TypeOf(rhs)){...}}

Some built-in contexts are provided in the contexts namespace, both for use and for reference.

Example code:

conststd=@import("std");constcomath=@import("comath");test{constctx=comath.ctx.simple({});constvalue=comath.eval("a * 2",ctx,.{.a=4})catch|err|switch(err){};trystd.testing.expect(value==8);}

Notable Implementations

To see an example of the terse notation enabled by comath, see zilliam.