Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement literals #44

Merged
merged 3 commits into from
Mar 9, 2024
Merged

Implement literals #44

merged 3 commits into from
Mar 9, 2024

Conversation

swazrgb
Copy link
Collaborator

@swazrgb swazrgb commented Feb 21, 2024

Scripts can assign numbers and entities using literal numbers & strings:

let num: Value = 10;
let id: Value = "c_battery";

Entity & number pairs can be assigned using the value builtin function, or as a casted object.

let pair1 = value("c_battery", 10);
let pair2 = {
  id: "c_battery",
  num: 10
} as ItemNum;

Coordinates can be assigned using the coord builtin function, or as a casted 2-element number array.

let coord1 = coord(10, 20);
let coord2 = [10, 20] as Coord;

One drawback of the new typing system is that arthimetrics aren't allowed by default, and the Value type has to be coerced to a number first. Fortunately this is easy to do:

let v: Value = "c_battery";
v = +v + +v; // prefix with +
v = v as number + 1; // cast
v = 1 + v; // reverse the expression if adding a constant

@swazrgb
Copy link
Collaborator Author

swazrgb commented Mar 8, 2024

@ribrdb ping

I've tried various alternatives since, mostly to work around having to write const v: Value = +v + +v for math, but nothing works well while still allowing literals such as "c_battery" or 5 to be assigned to Value typed variables: const v: Value = 5.

The best alternative would be requiring the usage of the value function in all cases, so const v: Value = value("c_battery") or const v: Value = value(5)

@ribrdb
Copy link
Owner

ribrdb commented Mar 8, 2024

I've tried various alternatives since, mostly to work around having to write const v: Value = +v + +v for math, but nothing works well while still allowing literals such as "c_battery" or 5 to be assigned to Value typed variables: const v: Value = 5.

I was thinking of just adding num: number to the BaseVar interface so you could optionally use v = v.num + v.num instead of unary-plus. I haven't tested to see if that would work though.

The best alternative would be requiring the usage of the value function in all cases, so const v: Value = value("c_battery") or const v: Value = value(5)

Actually I kind of like that

@swazrgb
Copy link
Collaborator Author

swazrgb commented Mar 8, 2024

I was thinking of just adding num: number to the BaseVar interface so you could optionally use v = v.num + v.num instead of unary-plus. I haven't tested to see if that would work though.

That should work. It feels a bit odd to me to provide a fake property for this. Internally the .num accessor would just be a no-op, existing purely to get the typescript to compile.

Actually I kind of like that

I don't mind it for variable assignments, but it's awkward for function calls. For example having to write entitiesInRange(5, value("v_mineable")) would be unfortunate.

This seems doable to support:

let v: Value; // Declare variable/params as Value
v = 5; // numbers are directly assignable
v = v + 5; // Values & numbers can be used in math as-is
v = value("metalore"); // string assingments must be wrapped in `value` 
v = value("metalore", 5); // NumPairs need the value function as well of course

v = "metalore"; // Not allowed! Must use value("metalore");

entitiesInRange(5, "v_mineable"); // literal strings can be supported as function arguments

I'll give this a go.

Scripts can assign numbers and entities using literal numbers & strings:

```typescript
let num: Value = 10;
let id: Value = "c_battery";
```

Entity & number pairs can be assigned using the `value` builtin function,
or as a casted object.

```typescript
let pair1 = value("c_battery", 10);
let pair2 = {
  id: "c_battery",
  num: 10
} as ItemNum;
```

Coordinates can be assigned using the `coord` builtin function,
or as a casted 2-element number array.

```typescript
let coord1 = coord(10, 20);
let coord2 = [10, 20] as Coord;
```

One drawback of the new typing system is that arthimetrics aren't allowed
by default, and the `Value` type has to be coerced to a number first.
Fortunately this is easy to do:

```
let v: Value = "c_battery";
v = +v + 1;
v = v as number + 1;
```
This allows math operations on Value types without any syntax tricks
@swazrgb
Copy link
Collaborator Author

swazrgb commented Mar 8, 2024

That was pretty straightforward. Could you please take another look, @ribrdb ?

compile.ts Show resolved Hide resolved
return dest;
} else if (ts.isArrayLiteralExpression(e)) {
let arr: number[] = [];
for(const property of e.elements) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed when there's the coord function?
If we do need it we should probably check the array length. I could certainly see people trying to use general arrays and getting confused.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implemented it because I saw the typescript definition type Coord = [number, number] which implies a user should be allowed to write this when specifying a coordinate. But I'd be happy to just get rid of it, the coord function is better ergonomics IMO.

Copy link
Collaborator Author

@swazrgb swazrgb Mar 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe change the Coord type to {x: number, y: number}, and allow this to be written literally? Just like {id: "metalore", num: 1} is also allowed to be written literally?

Or disallow writing both literally, and require usage of the coord and value functions? Then the type could change to:

class Coord {
  x: number;
  y: number;
  
  private constructor() {}
}

Or honestly maybe just class Coord {} (or just Value) because it's not like we can compile value.x (or value[0]) to anything sensible without calling separateCoordinates, which I'd prefer to be an explicit action.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I was only intending that to be used for arguments to functions which take a coordinate so you could enter a literal. You're right, an {x:, y:} object would probably be more clear.

compile.ts Outdated Show resolved Hide resolved
@ribrdb
Copy link
Owner

ribrdb commented Mar 9, 2024

This looks great, thanks! Just a couple comments

Fix typo in error message

Co-authored-by: Ryan Brown <ribrdb@gmail.com>
@ribrdb ribrdb merged commit 16992e5 into ribrdb:main Mar 9, 2024
3 checks passed
@swazrgb swazrgb mentioned this pull request Mar 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants