Skip to content

Constant evaluation of if/switch with const-evaluation expressions #55

@theCapypara

Description

@theCapypara

Summary

Add special support for const-evaluation in the headers of if/switch.

Dependencies

This needs the following features to be implemented first:

Motivation

This allows compile time logical evaluation, adding powerful meta-programming functionality to ExplorerScript.

Examples

def 0 {
  if (const %{3 > 5}) {
    thisWillNotHappen();
  } else {
    thisWillHappen();
  }
}

In this case only the else-branch is evaluated at compile time, only its operations are generated. No Branch opcodes or jumps are actually generated. This means this will be roughly equivalent to this SsbScript:

def 0 {
  thisWillHappen();
}
def 0 {
  switch (const %{3}) {
    case 1:
      foobar();
      break;
    case 3:
      // OPERATIONS STARTING HERE ARE ACTUALLY GENERATED
      baz();
    case 5:
      foo();
      // END
    case ${4}:
      break;
    case ${41 * 5}:
      break;
  }
}

A const-evaluated switch. Only the code for the second case is generated and for the third via fall-through (no break in the second case). Note that it does not matter if const-evaluation expressions is used in case blocks, this is not affected by this change at all and as is processed as normal in #54. However only simple case blocks are allowed, which means more complicated expressions do require const-evaluation expressions. This means this will be roughly equivalent to this SsbScript:

def 0 {
  baz();
  foo();
}

Language Changes

Parser and Lexer Changes

The const keyword is allowed as the first keyword in an if/switch header, if an if/switch header starts with const a const-evaluation statement must follow.

Behaviour

When an if/switch header consists of const and then a single const-evaluation expression these constructs must be evaluated completely different to their usual behaviour.

If / Elseif / Else

The expression in the header of the if's and elseif's are evaluated as would be the runtime-if blocks, however they values are evaluated at runtime. If the value in the header is an integer and >= 0 the condition passes. If it is not an integer this is a compile time error. Once a condition has passed, it's branch block is emitted, the other branch blocks are not emitted.

Switch

The value of the switch header is evaluated at compile-time. This switch only allows simple cases. The exact value of each case is checked against the value in the switch header. The first matching value causes the operations in the case to be taken until a break; or the end of the switch block is hit. No other cases are evaluated or operations are emitted (note however that fall-through is possible if no break; exists before another case is encountered. The cases are ignored in this case, as would be for the runtime-switches.

Loops (while/for)

Note that loops are omitted from this. They continue to function as before. There is no sense in allowing this sort of expression for loops, as it is not possible to assign macro variables at compile time. However compile time loops can be achieved using recursive macro calls.

Compiler Implementation

Compiler Interface Changes

No changes.

Decompiler Changes

No changes.

How to teach

Add this to the section on meta-programming introduced in #54.

Alternatives

  • Don't allow this
  • Use special syntax instead of "hijacking" existing if/switch.
  • Use a different scope for const if/switch.

Backwards compatibility

This is backwards incompatible as it changes the semantics of how the const-evaluation expression is interpreted inside of a if/switch. This feature should be shipped at the same time as #54. However this is fine, even if this feature is shipped later, as such a syntax would be unusual anyway (since it can just be replaced by omitting the const-evaluation block and directly using the value in most cases. In other cases it can be replaced via indirection with a macro call).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions