Skip to content

Commit

Permalink
feat: classes
Browse files Browse the repository at this point in the history
  • Loading branch information
zyrouge committed Jan 5, 2025
1 parent 8ffdb87 commit e0a9ec9
Show file tree
Hide file tree
Showing 68 changed files with 2,681 additions and 1,510 deletions.
1 change: 0 additions & 1 deletion packages/beize_compiler/example/main.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// ignore_for_file: avoid_print

import 'dart:typed_data';

import 'package:beize_compiler/beize_compiler.dart';
import 'package:beize_vm/beize_vm.dart';
import 'package:path/path.dart' as p;
Expand Down
27 changes: 15 additions & 12 deletions packages/beize_compiler/example/project/benchmark.beize
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
createBenchmarker := -> {
return {
startedAt: null,
endedAt: null,
start: -> {
this.startedAt = DateTime.now().millisecondsSinceEpoch;
},
end: -> {
this.endedAt = DateTime.now().millisecondsSinceEpoch;
print('Took ' + (this.endedAt - this.startedAt) + 'ms');
},
};
Benchmarker := $ {
static __name__: -> : "Benchmarker",
__constructor__: -> {
this.startedAt = null;
this.endedAt = null;
},
start: -> {
this.startedAt = DateTime.now().millisecondsSinceEpoch;
},
end: -> {
this.endedAt = DateTime.now().millisecondsSinceEpoch;
print('Took ' + (this.endedAt - this.startedAt) + 'ms');
},
};

print(Benchmarker);
16 changes: 8 additions & 8 deletions packages/beize_compiler/example/project/dev.beize
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
printHello := -> async {
print("Hello World");
Welcomer := $ {
static hello: "hello",
static __toString__: -> : "WelcomerToString",
__constructor__: -> {
this.hello2 = "hello";
},
__toString__: -> : "WelcomerToString2",
};

main := -> async {
printHello().await;
};

main().await;
print(Welcomer());
4 changes: 2 additions & 2 deletions packages/beize_compiler/example/project/main.beize
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "./benchmark.beize" only createBenchmarker;
import "./benchmark.beize" only Benchmarker;

benchmarker := createBenchmarker();
benchmarker := Benchmarker();
benchmarker.start();

increment := -> i {
Expand Down
70 changes: 62 additions & 8 deletions packages/beize_compiler/lib/compiler/parser/parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import '../compiler.dart';
import 'precedence.dart';
import 'rules.dart';

typedef _BeizeMatchableCase = ({
int start,
int thenJump,
int elseJump,
});

abstract class BeizeParser {
static Future<void> parseStatement(final BeizeCompiler compiler) async {
if (compiler.match(BeizeTokens.braceLeft)) {
Expand Down Expand Up @@ -277,7 +283,7 @@ abstract class BeizeParser {
compiler.consume(BeizeTokens.colon);
parseStatement(compiler);
final int exitJump = compiler.emitJump(BeizeOpCodes.opAbsoluteJump);
elseCase = _BeizeMatchableCase(start, exitJump, -1);
elseCase = (start: start, thenJump: exitJump, elseJump: -1);
} else {
matcher();
compiler.consume(BeizeTokens.colon);
Expand All @@ -288,7 +294,7 @@ abstract class BeizeParser {
compiler.patchJump(localJump);
compiler.emitOpCode(BeizeOpCodes.opPop);
final int thenJump = compiler.emitJump(BeizeOpCodes.opAbsoluteJump);
cases.add(_BeizeMatchableCase(start, thenJump, exitJump));
cases.add((start: start, thenJump: thenJump, elseJump: exitJump));
}
}
final int end = compiler.currentAbsoluteOffset;
Expand Down Expand Up @@ -450,6 +456,9 @@ abstract class BeizeParser {
case BeizeTokens.caret:
compiler.emitOpCode(BeizeOpCodes.opBitwiseXor);

case BeizeTokens.isKw:
compiler.emitOpCode(BeizeOpCodes.opIs);

default:
throw UnreachableException();
}
Expand Down Expand Up @@ -747,12 +756,57 @@ abstract class BeizeParser {
parseInfixExpression(compiler, BeizePrecedence.call);
compiler.patchJump(exitJump);
}
}

class _BeizeMatchableCase {
const _BeizeMatchableCase(this.start, this.thenJump, this.elseJump);
static void parseIs(final BeizeCompiler compiler) {
compiler.emitOpCode(BeizeOpCodes.opIs);
}

final int start;
final int thenJump;
final int elseJump;
static void parseClass(final BeizeCompiler compiler) {
int currentType = 0;
int currentCount = 0;
// this will be in format such as
// <static count>, <instance count>, <static count>, ...
final List<int> markings = <int>[];
bool cont = true;
compiler.consume(BeizeTokens.braceLeft);
while (cont && !compiler.check(BeizeTokens.braceRight)) {
final bool isStatic = compiler.match(BeizeTokens.staticKw);
if (compiler.match(BeizeTokens.bracketLeft)) {
parseExpression(compiler);
compiler.consume(BeizeTokens.bracketRight);
} else {
compiler.consume(BeizeTokens.identifier);
final String key = compiler.previousToken.literal as String;
compiler.emitConstant(key);
}
compiler.consume(BeizeTokens.colon);
if (isStatic) {
parseExpression(compiler);
if (currentType != 0) {
markings.add(currentCount);
currentType = 0;
currentCount = 0;
}
} else {
compiler.consume(BeizeTokens.rightArrow);
parseFunction(compiler);
if (currentType != 1) {
markings.add(currentCount);
currentType = 1;
currentCount = 0;
}
}
currentCount++;
cont = compiler.match(BeizeTokens.comma);
}
if (currentCount != 0) {
markings.add(currentCount);
}
compiler.consume(BeizeTokens.braceRight);
compiler.emitOpCode(BeizeOpCodes.opClass);
compiler.emitCode(markings.length);
for (final int x in markings) {
compiler.emitCode(x);
}
}
}
5 changes: 5 additions & 0 deletions packages/beize_compiler/lib/compiler/parser/rules.dart
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,17 @@ class BeizeParseRule {
precedence: BeizePrecedence.caret,
infix: BeizeParser.parseBinaryExpression,
),
BeizeTokens.isKw: BeizeParseRule(
precedence: BeizePrecedence.comparison,
infix: BeizeParser.parseBinaryExpression,
),
BeizeTokens.identifier: BeizeParseRule(prefix: BeizeParser.parseIdentifier),
BeizeTokens.number: BeizeParseRule(prefix: BeizeParser.parseNumber),
BeizeTokens.string: BeizeParseRule(prefix: BeizeParser.parseString),
BeizeTokens.trueKw: BeizeParseRule(prefix: BeizeParser.parseBoolean),
BeizeTokens.falseKw: BeizeParseRule(prefix: BeizeParser.parseBoolean),
BeizeTokens.nullKw: BeizeParseRule(prefix: BeizeParser.parseNull),
BeizeTokens.dollar: BeizeParseRule(prefix: BeizeParser.parseClass),
};

static BeizeParseRule of(final BeizeTokens type) => rules[type] ?? none;
Expand Down
14 changes: 14 additions & 0 deletions packages/beize_compiler/lib/disassembler/disassembler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,20 @@ class BeizeDisassembler {
);
return 1;

case BeizeOpCodes.opClass:
final int count = chunk.codeAt(ip + 1);
final List<int> markings = <int>[];
for (int i = 0; i < count; i++) {
markings.add(chunk.codeAt(ip + 1 + 1));
}
writeInstruction(
opCode,
ip,
chunk.lineAt(ip),
'{so}(markings = ${markings.join(' ')})',
);
return 1 + count;

default:
writeInstruction(opCode, ip, chunk.lineAt(ip));
return 0;
Expand Down
7 changes: 6 additions & 1 deletion packages/beize_compiler/lib/lexer/utils.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
class BeizeLexerUtils {
static bool isWhitespace(final String char) => char.trim().isEmpty;

static bool isNumeric(final String char) => '0123456789'.contains(char);

static bool isNumericContent(final String char) =>
'+-0123456789.exabcdef'.contains(char.toLowerCase());

static bool isQuote(final String char) =>
char == "'" || char == '"' || char == '`';

static bool isAlpha(final String char) =>
r'$_abcdefghijklmnopqrstuvwxyz'.contains(char.toLowerCase());
'_abcdefghijklmnopqrstuvwxyz'.contains(char.toLowerCase());

static bool isAlphaNumeric(final String char) =>
isAlpha(char) || isNumeric(char);
}
2 changes: 2 additions & 0 deletions packages/beize_compiler/lib/scanner/rules/identifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ abstract class BeizeIdentifierScanner {
BeizeTokens.asyncKw,
BeizeTokens.awaitKw,
BeizeTokens.onlyKw,
BeizeTokens.isKw,
BeizeTokens.staticKw,
};

static final Map<String, BeizeTokens> keywordsMap = keywords.asNameMap().map(
Expand Down
1 change: 1 addition & 0 deletions packages/beize_compiler/lib/scanner/rules/rules.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class BeizeScannerRules {
constructOffset1ScanFn(BeizeTokens.bang),
constructOffset1ScanFn(BeizeTokens.lesserThan),
constructOffset1ScanFn(BeizeTokens.greaterThan),
constructOffset1ScanFn(BeizeTokens.dollar),
],
);

Expand Down
6 changes: 6 additions & 0 deletions packages/beize_compiler/lib/token/tokens.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ enum BeizeTokens {
logicalOrEqual, // ||=
caretEqual, // ^=
nullOrEqual, // ??=
dollar, // $

trueKw, // true
falseKw, // false
Expand All @@ -80,6 +81,8 @@ enum BeizeTokens {
asyncKw, // async
awaitKw, // await
onlyKw, // only
isKw, // is
staticKw, // static
}

const Map<BeizeTokens, String> _tokensCodeMap = <BeizeTokens, String>{
Expand Down Expand Up @@ -140,6 +143,7 @@ const Map<BeizeTokens, String> _tokensCodeMap = <BeizeTokens, String>{
BeizeTokens.logicalOrEqual: '||=',
BeizeTokens.caretEqual: '^=',
BeizeTokens.nullOrEqual: '??=',
BeizeTokens.dollar: r'$',
BeizeTokens.trueKw: 'true',
BeizeTokens.falseKw: 'false',
BeizeTokens.ifKw: 'if',
Expand All @@ -161,6 +165,8 @@ const Map<BeizeTokens, String> _tokensCodeMap = <BeizeTokens, String>{
BeizeTokens.asyncKw: 'async',
BeizeTokens.awaitKw: 'await',
BeizeTokens.onlyKw: 'only',
BeizeTokens.isKw: 'is',
BeizeTokens.staticKw: 'static',
};

extension OutreTokensUtils on BeizeTokens {
Expand Down
2 changes: 2 additions & 0 deletions packages/beize_shared/lib/bytecode/op_codes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ enum BeizeOpCodes {
opBeginTry,
opEndTry,
opImport,
opIs,
opClass,
}
62 changes: 32 additions & 30 deletions packages/beize_vm/lib/errors/runtime_exception.dart
Original file line number Diff line number Diff line change
@@ -1,63 +1,65 @@
import '../bytecode.dart';
import '../values/exports.dart';
import 'native_exception.dart';

class BeizeRuntimeExpection extends BeizeNativeException {
BeizeRuntimeExpection(super.message);
class BeizeRuntimeException extends BeizeNativeException {
BeizeRuntimeException(super.message);

factory BeizeRuntimeExpection.invalidLeftOperandType(
factory BeizeRuntimeException.invalidLeftOperandType(
final String expected,
final String received,
) =>
BeizeRuntimeExpection(
BeizeRuntimeException(
'Invalid left operand value type (expected "$expected", received "$received")',
);

factory BeizeRuntimeExpection.invalidRightOperandType(
factory BeizeRuntimeException.invalidRightOperandType(
final String expected,
final String received,
) =>
BeizeRuntimeExpection(
BeizeRuntimeException(
'Invalid right operand value type (expected "$expected", received "$received")',
);

factory BeizeRuntimeExpection.undefinedVariable(final String name) =>
BeizeRuntimeExpection('Undefined variable "$name"');
factory BeizeRuntimeException.undefinedVariable(final String name) =>
BeizeRuntimeException('Undefined variable "$name"');

factory BeizeRuntimeExpection.cannotRedecalreVariable(final String name) =>
BeizeRuntimeExpection('Cannot redeclare variable "$name"');
factory BeizeRuntimeException.cannotRedeclareVariable(final String name) =>
BeizeRuntimeException('Cannot redeclare variable "$name"');

factory BeizeRuntimeExpection.unknownOpCode(final BeizeOpCodes opCode) =>
BeizeRuntimeExpection('Unknown op code: ${opCode.name}');
factory BeizeRuntimeException.unknownOpCode(final BeizeOpCodes opCode) =>
BeizeRuntimeException('Unknown op code: ${opCode.name}');

factory BeizeRuntimeExpection.unknownConstant(final dynamic constant) =>
BeizeRuntimeExpection('Unknown constant: $constant');
factory BeizeRuntimeException.unknownConstant(final dynamic constant) =>
BeizeRuntimeException('Unknown constant: $constant');

factory BeizeRuntimeExpection.cannotCastTo(
final BeizeValueKind expected,
final BeizeValueKind received,
factory BeizeRuntimeException.cannotCastTo(
final String expected,
final String received,
) =>
BeizeRuntimeExpection(
'Cannot cast "${received.code}" to "${expected.code}"',
BeizeRuntimeException(
'Cannot cast "$received" to "$expected"',
);

factory BeizeRuntimeExpection.unwrapFailed(final String message) =>
BeizeRuntimeExpection('Unwrap failed due to "$message"');
factory BeizeRuntimeException.unwrapFailed(final String message) =>
BeizeRuntimeException('Unwrap failed due to "$message"');

factory BeizeRuntimeExpection.cannotConvertDoubleToInteger(
factory BeizeRuntimeException.cannotConvertDoubleToInteger(
final double value,
) =>
BeizeRuntimeExpection('Cannot convert "$value" to integer');
BeizeRuntimeException('Cannot convert "$value" to integer');

factory BeizeRuntimeExpection.unexpectedArgumentType(
factory BeizeRuntimeException.unexpectedArgumentType(
final int index,
final BeizeValueKind expected,
final BeizeValueKind received,
final String expected,
final String received,
) =>
BeizeRuntimeExpection(
'Expected argument at $index to be "${expected.code}", received "${received.code}"',
BeizeRuntimeException(
'Expected argument at $index to be "$expected", received "$received"',
);

factory BeizeRuntimeException.notCallable(final String value) =>
BeizeRuntimeException('Value "$value" is not callable');

@override
String toString() => 'BeizeRuntimeExpection: $message';
String toString() => 'BeizeRuntimeException: $message';
}
Loading

0 comments on commit e0a9ec9

Please sign in to comment.