dart_eval icon indicating copy to clipboard operation
dart_eval copied to clipboard

Support for switch case

Open Noobware1 opened this issue 1 year ago • 3 comments

It is complicated to add? If not could you tell me how should I go on about it?

Noobware1 avatar Nov 08 '23 18:11 Noobware1

A full and complete implementation would be complicated, but a very simple implementation is probably fairly easy. Basically, you could just think of a switch case like:

switch(x) {
    case 1:
       i++;
       break;
    case 2:
       i += 2;
       break;
}

as a series of if/else expressions like:

if (x == 1) {
    i++;
} else if (x == 2) {
   i += 2;
}

That second block just uses if.dart and binary.dart to compile and you could look at what those do and basically copy it. To simplify things you could also say that only switch cases with break are allowed for now.

ethanblake4 avatar Nov 08 '23 20:11 ethanblake4

@ethanblake4 I am ashamed to ask but I literally can't find a way to make this happen. I have to main problems with implementing switch cases

  1. how can I know which case to execute
  2. unlike IfStatement's .thenStatement SwitchStatement member has statements a NodeList<Statement> how can I do anything with this.

I am really sorry for my shortcomings.

import 'package:dart_eval/src/eval/compiler/statement/statement.dart';
import 'package:dart_eval/src/eval/compiler/type.dart';
import 'package:dart_eval/src/eval/compiler/variable.dart';

StatementInfo compileSwitchStatement(
  SwitchStatement s,
  CompilerContext ctx,
  AlwaysReturnType? expectedReturnType,
) {
  final L = compileExpression(s.expression, ctx);

  Variable? R;
  for (var member in s.members) {
    if (member is SwitchPatternCase) {
      final pattern = member.guardedPattern.pattern;
      if (pattern is ConstantPattern) {
        R = compileExpression(pattern.expression, ctx);
        if (L == R) {
          break;
        }
      }
    }
  }
  return StatementInfo(-1, willAlwaysReturn: false, willAlwaysThrow: false);
}

Noobware1 avatar Dec 29 '23 10:12 Noobware1

  1. To generate code that checks if a variable L is equal to variable R (like does the variable match the expression of the switch case) you can do L.invoke(ctx, '==', [R]).

  2. Well basically you'd want to iterate through the NodeList and generate a macroBranch with an elseClause that generates a macroBranch for the next element in the list, so on and so forth, like try.dart does it here. Effectively turning something like this:

switch(x) {
    case 1:
       i++;
       break;
    case 2:
       i += 2;
       break;
    case 3;
       i += 3;
       break;
}

into

if (x == 1) {
    i++;
} else {
  if (x == 2) {
     i += 2;
  } else {
     if (x == 3) {
        i +=3;
     }
  }
}

If this is too hard then don't worry about it. It's not an ideal solution anyway because ultimately we'd actually want to construct a jump table and add a new switch bytecode.

ethanblake4 avatar Dec 31 '23 04:12 ethanblake4