Compare commits
24 Commits
9fdc003a71
...
7cddc62aaa
| Author | SHA1 | Date | |
|---|---|---|---|
|
7cddc62aaa
|
|||
|
49e00d9fbc
|
|||
|
1d2f98419e
|
|||
|
2a73dc3fef
|
|||
|
ede7396f9b
|
|||
| 6ca778dbfa | |||
|
672c9c0fa1
|
|||
|
dd2f3d6f6a
|
|||
|
ef9dd95844
|
|||
|
725e030374
|
|||
| db986d5242 | |||
|
3c97e75db6
|
|||
|
e0a468a2c2
|
|||
|
6740344eba
|
|||
|
4f9099a4c4
|
|||
|
5c66c4b645
|
|||
| c0896d2b9b | |||
|
607ff53987
|
|||
|
3268783cbe
|
|||
|
a48182a4e3
|
|||
|
205d19fb72
|
|||
|
10c6ea7dda
|
|||
|
1acf33f376
|
|||
|
aae481776f
|
@@ -1,48 +0,0 @@
|
||||
name: Compile manual
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- "**"
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest
|
||||
if: github.event.pull_request.draft == false
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: "3.2"
|
||||
|
||||
- name: Setup Fontist
|
||||
uses: fontist/setup-fontist@v2
|
||||
|
||||
- name: Install Fonts
|
||||
run: fontist manifest install docs/fonts.yaml
|
||||
|
||||
- uses: typst-community/setup-typst@v5
|
||||
with:
|
||||
typst-version: "0.15.0"
|
||||
zip-packages: docs/requirements.json
|
||||
cache-local-packages: true
|
||||
token: ""
|
||||
|
||||
- run: |
|
||||
typst compile \
|
||||
--root . \
|
||||
--font-path ~/.fontist/fonts \
|
||||
--input hash=${{ gitea.sha }} \
|
||||
docs/manual.typ \
|
||||
docs/manual.pdf
|
||||
|
||||
- name: Upload artifact
|
||||
uses: christopherhx/gitea-upload-artifact@v4
|
||||
with:
|
||||
name: manual
|
||||
path: docs/manual.pdf
|
||||
24
.gitea/workflows/tests.yaml
Normal file
24
.gitea/workflows/tests.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Tests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- "**"
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest
|
||||
if: github.event.pull_request.draft == false
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version-file: pyproject.toml
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
- run: python3 -m tests
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -6,4 +6,6 @@ venv
|
||||
*.pyc
|
||||
uv.lock
|
||||
.python-version
|
||||
/out
|
||||
/out
|
||||
/examples/**/build/
|
||||
/examples/**/*.pyi
|
||||
@@ -5,7 +5,7 @@ type Celsius = float
|
||||
type Kelvin = float where _ >= 0
|
||||
type Hectopascal = float
|
||||
|
||||
type Temperature = Celsius where in_range(-30.0, 100.0)
|
||||
type Temperature = Celsius where in_range(-30.0, 100.0)(_)
|
||||
type Pressure = Hectopascal where in_range(800.0, 1100.0)(_)
|
||||
type Humidity = float where is_percentage(_)
|
||||
type HeatIndex = float
|
||||
@@ -38,7 +38,7 @@ alias RawData = Frame[
|
||||
|
||||
alias Data = Frame[
|
||||
station_id: StationID,
|
||||
timestamp: object,
|
||||
timestamp: Any,
|
||||
temperature: Temperature,
|
||||
pressure: Pressure,
|
||||
humidity: Humidity,
|
||||
@@ -46,7 +46,7 @@ alias Data = Frame[
|
||||
|
||||
alias DataWithHI = Frame[
|
||||
station_id: StationID,
|
||||
timestamp: object,
|
||||
timestamp: Any,
|
||||
temperature: Temperature,
|
||||
pressure: Pressure,
|
||||
humidity: Humidity,
|
||||
@@ -54,12 +54,12 @@ alias DataWithHI = Frame[
|
||||
]
|
||||
|
||||
alias DailyAverages = Frame[
|
||||
timestamp: object,
|
||||
timestamp: Any,
|
||||
temperature: Mean[Temperature],
|
||||
pressure: Mean[Pressure],
|
||||
humidity: Mean[Humidity],
|
||||
heat_index: Mean[HeatIndex],
|
||||
]
|
||||
|
||||
predicate limit_amplitude(max_amp: float)(ls: list[float]) = max(ls) - min(ls) <= max_amp
|
||||
type LowAmplitudeWave = list[float where _ >= 1] where limit_amplitude(10)(_)
|
||||
// predicate limit_amplitude(max_amp: float)(ls: list[float]) = max(ls) - min(ls) <= max_amp
|
||||
// type LowAmplitudeWave = list[float where _ >= 1] where limit_amplitude(10)(_)
|
||||
|
||||
@@ -11,7 +11,7 @@ delta = end_ts - start_ts
|
||||
|
||||
min_temp, max_temp = -30.0, 100.0
|
||||
min_pres, max_pres = 800.0, 1100.0
|
||||
min_hum, max_hum = 0.0, 1.0
|
||||
min_hum, max_hum = 0.0, 100.0
|
||||
|
||||
N = 3000
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ def daily_avg(df: DataWithHI):
|
||||
DailyAverages,
|
||||
df.groupby(
|
||||
by=[
|
||||
df["station_id"],
|
||||
"station_id",
|
||||
df["timestamp"].dt.day.rename("day"),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -136,15 +136,6 @@ class ConstraintType:
|
||||
constraint: Expr
|
||||
|
||||
|
||||
class ComplexType:
|
||||
members: list[MemberStmt]
|
||||
|
||||
|
||||
class ExtensionType:
|
||||
base: Type
|
||||
extension: ComplexType
|
||||
|
||||
|
||||
class FunctionType:
|
||||
params: ParamSpec
|
||||
returns: Type
|
||||
|
||||
@@ -256,12 +256,6 @@ class Type(ABC):
|
||||
@abstractmethod
|
||||
def visit_constraint_type(self, type: ConstraintType) -> T: ...
|
||||
|
||||
@abstractmethod
|
||||
def visit_complex_type(self, type: ComplexType) -> T: ...
|
||||
|
||||
@abstractmethod
|
||||
def visit_extension_type(self, type: ExtensionType) -> T: ...
|
||||
|
||||
@abstractmethod
|
||||
def visit_function_type(self, type: FunctionType) -> T: ...
|
||||
|
||||
@@ -295,23 +289,6 @@ class ConstraintType(Type):
|
||||
return visitor.visit_constraint_type(self)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ComplexType(Type):
|
||||
members: list[MemberStmt]
|
||||
|
||||
def accept(self, visitor: Type.Visitor[T]) -> T:
|
||||
return visitor.visit_complex_type(self)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ExtensionType(Type):
|
||||
base: Type
|
||||
extension: ComplexType
|
||||
|
||||
def accept(self, visitor: Type.Visitor[T]) -> T:
|
||||
return visitor.visit_extension_type(self)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FunctionType(Type):
|
||||
params: ParamSpec
|
||||
|
||||
@@ -124,19 +124,6 @@ class MidasPrinter(
|
||||
res += " where " + type.constraint.accept(self)
|
||||
return res
|
||||
|
||||
def visit_complex_type(self, type: m.ComplexType) -> str:
|
||||
res: str = "{\n"
|
||||
self.level += 1
|
||||
for member in type.members:
|
||||
res += member.accept(self)
|
||||
res += "\n"
|
||||
self.level -= 1
|
||||
res += self.indented("}")
|
||||
return res
|
||||
|
||||
def visit_extension_type(self, type: m.ExtensionType) -> str:
|
||||
return f"{type.base.accept(self)} & {type.extension.accept(self)}"
|
||||
|
||||
def visit_function_type(self, type: m.FunctionType) -> str:
|
||||
spec: str = self._visit_param_spec(type.params)
|
||||
return f"fn {spec} -> {type.returns.accept(self)}"
|
||||
|
||||
@@ -177,21 +177,6 @@ class MidasAstPrinter(
|
||||
with self._child_level(single=True):
|
||||
type.constraint.accept(self)
|
||||
|
||||
def visit_complex_type(self, type: m.ComplexType) -> None:
|
||||
self._write_line("ComplexType")
|
||||
with self._child_level():
|
||||
self._write_sequence("members", type.members, last=True)
|
||||
|
||||
def visit_extension_type(self, type: m.ExtensionType) -> None:
|
||||
self._write_line("ExtensionType")
|
||||
with self._child_level():
|
||||
self._write_line("base")
|
||||
with self._child_level(single=True):
|
||||
type.base.accept(self)
|
||||
self._write_line("extension", last=True)
|
||||
with self._child_level(single=True):
|
||||
type.extension.accept(self)
|
||||
|
||||
def visit_function_type(self, type: m.FunctionType) -> None:
|
||||
self._write_line("FunctionType")
|
||||
with self._child_level():
|
||||
|
||||
@@ -51,24 +51,25 @@ class FrameGroupByMethodRegistry(MethodRegistry[Call]):
|
||||
new_columns: list[DataFrameType.Column] = []
|
||||
|
||||
for column in call.groupby.frame.columns:
|
||||
column_groupby: ColumnGroupBy = ColumnGroupBy(column=column.type)
|
||||
result_type: Type = self.typer.call_method(
|
||||
location=call.location,
|
||||
call_expr=call.call_expr,
|
||||
obj=(call.groupby_expr, column_groupby),
|
||||
method_name=method,
|
||||
positional=call.positional,
|
||||
keywords=call.keywords,
|
||||
)
|
||||
if not isinstance(result_type, ColumnType):
|
||||
result_type = ColumnType(type=UnknownType())
|
||||
new_columns.append(
|
||||
DataFrameType.Column(
|
||||
index=column.index,
|
||||
name=column.name,
|
||||
type=result_type,
|
||||
with self.reporter.with_context(f"in column '{column.name}'"):
|
||||
column_groupby: ColumnGroupBy = ColumnGroupBy(column=column.type)
|
||||
result_type: Type = self.typer.call_method(
|
||||
location=call.location,
|
||||
call_expr=call.call_expr,
|
||||
obj=(call.groupby_expr, column_groupby),
|
||||
method_name=method,
|
||||
positional=call.positional,
|
||||
keywords=call.keywords,
|
||||
)
|
||||
if not isinstance(result_type, ColumnType):
|
||||
result_type = ColumnType(type=UnknownType())
|
||||
new_columns.append(
|
||||
DataFrameType.Column(
|
||||
index=column.index,
|
||||
name=column.name,
|
||||
type=result_type,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return DataFrameType(columns=new_columns)
|
||||
|
||||
|
||||
@@ -159,7 +159,10 @@ class FrameMethodRegistry(MethodRegistry[Call]):
|
||||
col_type2 = ColumnType(type=operand[1])
|
||||
|
||||
if col_type2 is not None:
|
||||
col_type = self._get_method_result(call, col_type1, col_type2, method)
|
||||
with self.reporter.with_context(f"in column '{column.name}'"):
|
||||
col_type = self._get_method_result(
|
||||
call, col_type1, col_type2, method
|
||||
)
|
||||
|
||||
new_column = DataFrameType.Column(
|
||||
index=column.index,
|
||||
@@ -595,8 +598,62 @@ class FrameMethodRegistry(MethodRegistry[Call]):
|
||||
)
|
||||
return result.result
|
||||
|
||||
def _filter_groupby_columns(
|
||||
self, frame: DataFrameType, by: TypedExpr
|
||||
) -> DataFrameType:
|
||||
"""Remove columns passed as string literals in groupby's `by` argument
|
||||
|
||||
Args:
|
||||
frame (DataFrameType): the original dataframe
|
||||
by (TypedExpr): the by argument
|
||||
|
||||
Returns:
|
||||
DataFrameType: the filtered dataframe
|
||||
"""
|
||||
by_columns: list[str] = []
|
||||
|
||||
by_expr, _ = by
|
||||
|
||||
match by_expr:
|
||||
case p.ListExpr(items=items):
|
||||
for item in items:
|
||||
match item:
|
||||
case p.LiteralExpr(value=str() as name):
|
||||
by_columns.append(name)
|
||||
|
||||
case p.LiteralExpr(value=str() as name):
|
||||
by_columns.append(name)
|
||||
|
||||
if len(by_columns) == 0:
|
||||
return frame
|
||||
|
||||
new_columns: list[DataFrameType.Column] = []
|
||||
for column in frame.columns:
|
||||
if column.name in by_columns:
|
||||
continue
|
||||
new_columns.append(
|
||||
DataFrameType.Column(
|
||||
index=len(new_columns),
|
||||
name=column.name,
|
||||
type=column.type,
|
||||
)
|
||||
)
|
||||
|
||||
return DataFrameType(columns=new_columns)
|
||||
|
||||
@method()
|
||||
def groupby(self, call: Call) -> Type:
|
||||
new_frame: DataFrameType = call.frame
|
||||
|
||||
by: Optional[TypedExpr] = None
|
||||
if len(call.positional) != 0:
|
||||
by = call.positional[0]
|
||||
elif "by" in call.keywords:
|
||||
by = call.keywords["by"]
|
||||
|
||||
if by is not None:
|
||||
new_frame = self._filter_groupby_columns(call.frame, by)
|
||||
|
||||
bool_: Type = self.types.get_type("bool")
|
||||
function: Function = Function(
|
||||
params=ParamSpec(
|
||||
@@ -626,7 +683,7 @@ class FrameMethodRegistry(MethodRegistry[Call]):
|
||||
)
|
||||
],
|
||||
),
|
||||
returns=FrameGroupBy(frame=call.frame),
|
||||
returns=FrameGroupBy(frame=new_frame),
|
||||
)
|
||||
|
||||
result: CallResult = self.dispatcher.get_result(
|
||||
|
||||
@@ -13,11 +13,9 @@ from midas.checker.registry import TypesRegistry
|
||||
from midas.checker.reporter import FileReporter, Reporter
|
||||
from midas.checker.types import (
|
||||
ColumnType,
|
||||
ComplexType,
|
||||
ConstraintType,
|
||||
DataFrameType,
|
||||
DerivedType,
|
||||
ExtensionType,
|
||||
Function,
|
||||
GenericType,
|
||||
ParamSpec,
|
||||
@@ -407,24 +405,21 @@ class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type
|
||||
return UnknownType()
|
||||
|
||||
def visit_constraint_type(self, type: m.ConstraintType) -> Type:
|
||||
base_type: Type = type.type.accept(self)
|
||||
self._predicate_params["_"] = base_type
|
||||
constraint_type: Type = self.type_of(type.constraint)
|
||||
self._predicate_params = {}
|
||||
if not self.types.is_subtype(constraint_type, self._bool):
|
||||
self.reporter.error(
|
||||
type.location,
|
||||
f"Constraint must evaluate to a boolean, got {constraint_type}",
|
||||
)
|
||||
|
||||
return ConstraintType(
|
||||
type=type.type.accept(self),
|
||||
type=base_type,
|
||||
constraint=type.constraint,
|
||||
)
|
||||
|
||||
def visit_complex_type(self, type: m.ComplexType) -> ComplexType:
|
||||
return ComplexType(
|
||||
members={
|
||||
member.name.lexeme: member.type.accept(self) for member in type.members
|
||||
}
|
||||
)
|
||||
|
||||
def visit_extension_type(self, type: m.ExtensionType) -> Type:
|
||||
return ExtensionType(
|
||||
base=type.base.accept(self),
|
||||
extension=self.visit_complex_type(type.extension),
|
||||
)
|
||||
|
||||
def visit_function_type(self, type: m.FunctionType) -> Type:
|
||||
return Function(
|
||||
params=self._visit_param_spec(type.params),
|
||||
|
||||
@@ -257,6 +257,9 @@ class PythonTyper(
|
||||
"""
|
||||
unfolded: Type = unfold_type(obj[1])
|
||||
match unfolded:
|
||||
case TopType() | UnknownType():
|
||||
return UnknownType()
|
||||
|
||||
case DataFrameType():
|
||||
return self.frame_mgr.call(
|
||||
method=method_name,
|
||||
|
||||
@@ -8,11 +8,9 @@ from midas.checker.types import (
|
||||
AppliedType,
|
||||
BaseType,
|
||||
ColumnType,
|
||||
ComplexType,
|
||||
ConstraintType,
|
||||
DataFrameType,
|
||||
DerivedType,
|
||||
ExtensionType,
|
||||
Function,
|
||||
GenericType,
|
||||
OverloadedFunction,
|
||||
@@ -202,14 +200,6 @@ class TypesRegistry:
|
||||
case (BaseType(name=name1), BaseType(name=name2)):
|
||||
return self.is_builtin_subtype(name1, name2)
|
||||
|
||||
case (ComplexType(properties=props1), ComplexType(properties=props2)):
|
||||
for k, t in props2.items():
|
||||
if k not in props1:
|
||||
return False
|
||||
if not self.is_subtype(props1[k], t):
|
||||
return False
|
||||
return True
|
||||
|
||||
case (DataFrameType(columns=columns1), DataFrameType(columns=columns2)):
|
||||
# TODO: check order?
|
||||
by_name1: dict[str, DataFrameType.Column] = {
|
||||
@@ -506,20 +496,6 @@ class TypesRegistry:
|
||||
member_type2 = substitute_typevars(member_type2, substitutions)
|
||||
return member_type2
|
||||
|
||||
case ComplexType(members=members):
|
||||
if member_name in members:
|
||||
return members[member_name]
|
||||
self.logger.debug(f"No member '{member_name}' in {type}")
|
||||
return None
|
||||
|
||||
case ExtensionType(base=base, extension=ComplexType(members=members)):
|
||||
if member_name in members:
|
||||
return members[member_name]
|
||||
self.logger.debug(
|
||||
f"No member '{member_name}' on {type}, looking up in base"
|
||||
)
|
||||
return self.lookup_member(base, member_name)
|
||||
|
||||
case ConstraintType(type=base):
|
||||
return self.lookup_member(base, member_name)
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import contextmanager
|
||||
from typing import Optional
|
||||
|
||||
from midas.ast.location import Location
|
||||
@@ -54,6 +55,7 @@ class FileReporter:
|
||||
def __init__(self, base_reporter: Reporter, path: Optional[str]) -> None:
|
||||
self.base_reporter: Reporter = base_reporter
|
||||
self.path: Optional[str] = path
|
||||
self._context: list[str] = []
|
||||
|
||||
def for_file(self, path: Optional[str]) -> FileReporter:
|
||||
"""Create a new file reporter for the given path with the same base reporter
|
||||
@@ -66,6 +68,14 @@ class FileReporter:
|
||||
"""
|
||||
return FileReporter(self.base_reporter, path)
|
||||
|
||||
@contextmanager
|
||||
def with_context(self, ctx: str):
|
||||
self._context.append(ctx)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
self._context.pop()
|
||||
|
||||
def report(self, type: DiagnosticType, location: Location, message: str):
|
||||
"""Report a diagnostic to the base reporter
|
||||
|
||||
@@ -74,6 +84,8 @@ class FileReporter:
|
||||
location (Location): the location of the diagnostic in the file
|
||||
message (str): the diagnostic's message
|
||||
"""
|
||||
for ctx in self._context:
|
||||
message = message + ", " + ctx
|
||||
self.base_reporter.report(self.path, type, location, message)
|
||||
|
||||
def error(self, location: Location, message: str):
|
||||
|
||||
@@ -113,28 +113,6 @@ class OverloadedFunction:
|
||||
return "<overloaded function>"
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class ComplexType:
|
||||
"""A type with inline members"""
|
||||
|
||||
members: dict[str, Type]
|
||||
|
||||
def __str__(self) -> str:
|
||||
props: list[str] = [f"{name}: {type}" for name, type in self.members.items()]
|
||||
return f"{{{', '.join(props)}}}"
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class ExtensionType:
|
||||
"""An extension of a type, adding members through a `ComplexType`"""
|
||||
|
||||
base: Type
|
||||
extension: ComplexType
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.base} & {self.extension}"
|
||||
|
||||
|
||||
class Variance(StrEnum):
|
||||
"""The variance of a :class:`TypeVar`"""
|
||||
|
||||
@@ -323,24 +301,6 @@ def substitute_typevars(type: Type, substitutions: dict[str, Type]) -> Type:
|
||||
]
|
||||
)
|
||||
|
||||
case ComplexType(members=members):
|
||||
members2: dict[str, Type] = {
|
||||
name: substitute_typevars(prop, substitutions)
|
||||
for name, prop in members.items()
|
||||
}
|
||||
return ComplexType(members=members2)
|
||||
|
||||
case ExtensionType(base=base, extension=ComplexType(members=members)):
|
||||
return ExtensionType(
|
||||
base=substitute_typevars(base, substitutions),
|
||||
extension=ComplexType(
|
||||
members={
|
||||
name: substitute_typevars(prop, substitutions)
|
||||
for name, prop in members.items()
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
case AppliedType(name=name, args=args, body=body):
|
||||
return AppliedType(
|
||||
name=name,
|
||||
@@ -468,9 +428,6 @@ def to_annotation(type: Type) -> str:
|
||||
case OverloadedFunction():
|
||||
return "Callable"
|
||||
|
||||
case ComplexType() | ExtensionType():
|
||||
raise NotImplementedError
|
||||
|
||||
case TypeVar(name=name):
|
||||
return name
|
||||
|
||||
@@ -519,8 +476,6 @@ Type = (
|
||||
| UnitType
|
||||
| Function
|
||||
| OverloadedFunction
|
||||
| ComplexType
|
||||
| ExtensionType
|
||||
| TypeVar
|
||||
| GenericType
|
||||
| AppliedType
|
||||
|
||||
@@ -338,21 +338,11 @@ class MidasHighlighter(
|
||||
type.type.accept(self)
|
||||
type.constraint.accept(self)
|
||||
|
||||
def visit_complex_type(self, type: m.ComplexType) -> None:
|
||||
self.wrap(type, "complex-type")
|
||||
for member in type.members:
|
||||
member.accept(self)
|
||||
|
||||
def visit_function_type(self, type: m.FunctionType) -> None:
|
||||
self.wrap(type, "function")
|
||||
self._visit_param_spec(type.params)
|
||||
type.returns.accept(self)
|
||||
|
||||
def visit_extension_type(self, type: m.ExtensionType) -> None:
|
||||
self.wrap(type, "extension")
|
||||
type.base.accept(self)
|
||||
type.extension.accept(self)
|
||||
|
||||
def _visit_param_spec(self, spec: m.ParamSpec) -> None:
|
||||
for param in spec.pos + spec.mixed + spec.kw:
|
||||
param.type.accept(self)
|
||||
|
||||
@@ -7,8 +7,7 @@ span {
|
||||
|
||||
&.named-type,
|
||||
&.generic-type,
|
||||
&.constraint-type,
|
||||
&.complex-type {
|
||||
&.constraint-type {
|
||||
--col: 150, 150, 150;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,9 @@ from midas.checker.types import (
|
||||
BaseType,
|
||||
ColumnGroupBy,
|
||||
ColumnType,
|
||||
ComplexType,
|
||||
ConstraintType,
|
||||
DataFrameType,
|
||||
DerivedType,
|
||||
ExtensionType,
|
||||
FrameGroupBy,
|
||||
Function,
|
||||
GenericType,
|
||||
@@ -675,8 +673,6 @@ class Generator(p.Stmt.Visitor[ast.stmt], p.Expr.Visitor[ast.expr]):
|
||||
case (
|
||||
Function()
|
||||
| OverloadedFunction()
|
||||
| ComplexType()
|
||||
| ExtensionType()
|
||||
| GenericType()
|
||||
| FrameGroupBy()
|
||||
| ColumnGroupBy()
|
||||
|
||||
@@ -8,11 +8,9 @@ from midas.checker.types import (
|
||||
BaseType,
|
||||
ColumnGroupBy,
|
||||
ColumnType,
|
||||
ComplexType,
|
||||
ConstraintType,
|
||||
DataFrameType,
|
||||
DerivedType,
|
||||
ExtensionType,
|
||||
FrameGroupBy,
|
||||
Function,
|
||||
GenericType,
|
||||
@@ -269,14 +267,6 @@ class StubsGenerator:
|
||||
right=self.dump_type(overloads[-1]),
|
||||
)
|
||||
|
||||
case ComplexType():
|
||||
name: str = self.new_stub_name()
|
||||
self.generate_stub(name, type)
|
||||
return ast.Name(id=name)
|
||||
|
||||
case ExtensionType():
|
||||
raise NotImplementedError
|
||||
|
||||
case TypeVar():
|
||||
return ast.Name(id=type.name)
|
||||
|
||||
|
||||
@@ -5,11 +5,9 @@ from midas.ast.midas import (
|
||||
AliasStmt,
|
||||
BinaryExpr,
|
||||
CallExpr,
|
||||
ComplexType,
|
||||
ConstraintType,
|
||||
Expr,
|
||||
ExtendStmt,
|
||||
ExtensionType,
|
||||
FrameType,
|
||||
FunctionType,
|
||||
GenericType,
|
||||
@@ -187,19 +185,9 @@ class MidasParser(Parser[list[Stmt]]):
|
||||
Returns:
|
||||
TypeExpr: the parsed type expression
|
||||
"""
|
||||
base: Type
|
||||
if self.match(TokenType.FUNC):
|
||||
base = self.function()
|
||||
else:
|
||||
base = self.constraint_type()
|
||||
if self.match(TokenType.AND):
|
||||
extension: ComplexType = self.complex_type()
|
||||
return ExtensionType(
|
||||
location=Location.span(base.location, extension.location),
|
||||
base=base,
|
||||
extension=extension,
|
||||
)
|
||||
return base
|
||||
return self.function()
|
||||
return self.constraint_type()
|
||||
|
||||
def constraint_type(self) -> Type:
|
||||
"""Parse a constraint type expression
|
||||
@@ -235,9 +223,6 @@ class MidasParser(Parser[list[Stmt]]):
|
||||
self.consume(TokenType.RIGHT_PAREN, "Unclosed parenthesis")
|
||||
return type
|
||||
|
||||
if self.check(TokenType.LEFT_BRACE):
|
||||
return self.complex_type()
|
||||
|
||||
return self.generic_type()
|
||||
|
||||
def generic_type(self) -> Type:
|
||||
@@ -295,34 +280,6 @@ class MidasParser(Parser[list[Stmt]]):
|
||||
name=name,
|
||||
)
|
||||
|
||||
def complex_type(self) -> ComplexType:
|
||||
"""Parse a complex type expression
|
||||
|
||||
A complex type consists of zero or more member statements enclosed in
|
||||
curly braces
|
||||
|
||||
Returns:
|
||||
ComplexType: the parsed complex type expression
|
||||
"""
|
||||
left: Token = self.consume(
|
||||
TokenType.LEFT_BRACE, "Expected '{' to start type body"
|
||||
)
|
||||
members: list[MemberStmt] = []
|
||||
# TODO: add keyword to differentiate properties and methods,
|
||||
# and allow multiple methods with the same name but not properties
|
||||
names: set[str] = set()
|
||||
while not self.check(TokenType.RIGHT_BRACE) and not self.is_at_end():
|
||||
member: MemberStmt = self.member_stmt()
|
||||
# if member.name.lexeme in names:
|
||||
# raise self.error(member.name, "Duplicate property")
|
||||
# names.add(member.name.lexeme)
|
||||
members.append(member)
|
||||
right: Token = self.consume(TokenType.RIGHT_BRACE, "Unclosed type body")
|
||||
return ComplexType(
|
||||
location=left.location_to(right),
|
||||
members=members,
|
||||
)
|
||||
|
||||
def frame_type(self) -> FrameType:
|
||||
"""Parse a frame type expression
|
||||
|
||||
@@ -632,7 +589,7 @@ class MidasParser(Parser[list[Stmt]]):
|
||||
return WildcardExpr(location=token.get_location(), token=token)
|
||||
|
||||
if self.match(TokenType.LEFT_PAREN):
|
||||
expr: Expr = self.constraint()
|
||||
expr: Expr = self.expression()
|
||||
right: Token = self.consume(TokenType.RIGHT_PAREN, "Unclosed parenthesis")
|
||||
return GroupingExpr(location=token.location_to(right), expr=expr)
|
||||
|
||||
|
||||
@@ -380,7 +380,7 @@ class PythonParser:
|
||||
for col in cols:
|
||||
columns.append(self._parse_frame_column(col))
|
||||
|
||||
case ast.Slice() | ast.Name():
|
||||
case ast.Slice() | ast.Name() | ast.Subscript():
|
||||
columns.append(self._parse_frame_column(schema))
|
||||
|
||||
case _:
|
||||
@@ -391,7 +391,7 @@ class PythonParser:
|
||||
def _parse_frame_column(self, column: ast.expr) -> FrameColumn:
|
||||
loc: Location = Location.from_ast(column)
|
||||
match column:
|
||||
case ast.Name():
|
||||
case ast.Name() | ast.Subscript():
|
||||
return FrameColumn(
|
||||
location=loc,
|
||||
name=None,
|
||||
|
||||
@@ -1,20 +1,8 @@
|
||||
identifier ::= '[a-zA-Z][a-zA-Z_]*'
|
||||
Identifier ::= '[a-zA-Z][a-zA-Z_]*'
|
||||
|
||||
integer ::= '\d+'
|
||||
number ::= integer ["." integer]
|
||||
boolean ::= "False" | "True"
|
||||
none ::= "None"
|
||||
TypeArgs ::= "[" (Type ("," Type)*)? "]"
|
||||
|
||||
value ::= number | boolean | none
|
||||
lambda-value ::= "_" | value
|
||||
lambda-operator ::= ">" | "<" | ">=" | "<=" | "==" | "!="
|
||||
lambda ::= lambda-value lambda-operator lambda-value
|
||||
FrameColumn ::= ((Identifier | "_") ":")? Type
|
||||
FrameSchema ::= "[" (FrameColumn ("," FrameColumn)*)? "]"
|
||||
|
||||
constraint ::= identifier | "(" lambda ")"
|
||||
base-type ::= identifier
|
||||
type ::= base-type { "+" constraint }
|
||||
|
||||
column-type ::= type | "_"
|
||||
column-def ::= [ identifier ":" ] column-type
|
||||
|
||||
frame-def ::= column-def { "," column-def }
|
||||
Type ::= "Frame" FrameSchema | Identifier TypeArgs?
|
||||
|
||||
@@ -1,64 +1,72 @@
|
||||
#import "@preview/fervojo:0.1.1": render
|
||||
#import "@preview/fervojo:0.1.1": default-css, render
|
||||
|
||||
#let value = ```
|
||||
{[`value` <
|
||||
[`number` 'digit' * ! <!, ["." 'digit' * !]>],
|
||||
[`boolean` <"False", "True">],
|
||||
[`none` "None"]
|
||||
#let extra-css = ```css
|
||||
svg.railroad .terminal rect {
|
||||
fill: #F7DCD4;
|
||||
}
|
||||
```
|
||||
#let css = default-css() + bytes(extra-css.text)
|
||||
|
||||
#let type-args = ```
|
||||
{[`type-args` "[" <!, 'type'*","> "]"]}
|
||||
```
|
||||
|
||||
#let frame-schema = ```
|
||||
{[`frame-schema` "[" <!, [[<'identifier', "_"> ":"]? 'type']*","> "]"]}
|
||||
```
|
||||
|
||||
#let type = ```
|
||||
{[`type` <
|
||||
["Frame" 'frame-schema'],
|
||||
['identifier' <!, 'type-args'>]
|
||||
>]}
|
||||
```
|
||||
|
||||
#let constraint = ```
|
||||
{[`constraint` <"_", 'value'> <">", "<", ">=", "<=", "==", "!="> <"_", 'value'>]}
|
||||
```
|
||||
|
||||
#let type-with-constraints = ```
|
||||
{[`type-with-constraints` 'identifier' <!, ["+" "(" 'constraint' ")"] * !>]}
|
||||
```
|
||||
|
||||
#let column-def = ```
|
||||
{[`column-def` <!, ['identifier' ":"]> <"_", 'type-with-constraints'>]}
|
||||
```
|
||||
|
||||
#let frame-def = ```
|
||||
{[`frame-def` 'column-def' * ","]}
|
||||
```
|
||||
|
||||
#let annotation = ```
|
||||
{[`annotation` 'identifier' <!, ["[" 'frame-def' "]"]>]}
|
||||
```
|
||||
|
||||
#let rules = (
|
||||
value,
|
||||
constraint,
|
||||
type-with-constraints,
|
||||
column-def,
|
||||
frame-def,
|
||||
annotation,
|
||||
type-args: type-args,
|
||||
frame-schema: frame-schema,
|
||||
type: type,
|
||||
)
|
||||
|
||||
#let inline = (
|
||||
"type-args",
|
||||
"frame-schema",
|
||||
)
|
||||
|
||||
#set text(font: "Source Sans 3")
|
||||
|
||||
= Type annotation syntax
|
||||
#title[Supported Python annotation syntax]
|
||||
|
||||
#for rule in rules {
|
||||
render(rule)
|
||||
}
|
||||
= Outline
|
||||
|
||||
/*
|
||||
#let by-name = (
|
||||
annotation: annotation,
|
||||
frame-def: frame-def,
|
||||
column-def: column-def,
|
||||
type-with-constraints: type-with-constraints,
|
||||
constraint: constraint,
|
||||
value: value,
|
||||
#box(
|
||||
columns(
|
||||
2,
|
||||
outline(title: none),
|
||||
),
|
||||
height: 9cm,
|
||||
stroke: 1pt,
|
||||
inset: 1em,
|
||||
)
|
||||
|
||||
|
||||
= Statements and expressions
|
||||
|
||||
#for (name, rule) in rules.pairs().rev() {
|
||||
[== #name]
|
||||
render(rule, css: css)
|
||||
}
|
||||
|
||||
#let substitute(base-rule) = {
|
||||
let new-rule = base-rule
|
||||
for (key, rule) in by-name.pairs() {
|
||||
new-rule = new-rule.replace("'" + key + "'", rule.text.slice(1, -1))
|
||||
for name in inline {
|
||||
let rule = rules.at(name)
|
||||
let replacement = rule.text.slice(1, -1).replace(regex("\[`.*?`"), "[")
|
||||
replacement = "[" + replacement + "#`" + name + "`]"
|
||||
new-rule = new-rule.replace(
|
||||
"'" + name + "'",
|
||||
replacement,
|
||||
)
|
||||
}
|
||||
if new-rule != base-rule {
|
||||
new-rule = substitute(new-rule)
|
||||
@@ -66,9 +74,16 @@
|
||||
return new-rule
|
||||
}
|
||||
|
||||
#let combined = raw(substitute(annotation.text))
|
||||
|
||||
|
||||
#set page(flipped: true)
|
||||
#render(combined)
|
||||
*/
|
||||
|
||||
|
||||
= Combined rules
|
||||
|
||||
#for (name, rule) in rules.pairs() {
|
||||
if not name in inline {
|
||||
[== #name]
|
||||
let combined = substitute(rule.text)
|
||||
render(raw(combined), css: css)
|
||||
//raw(block: true, combined)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,40 +4,85 @@ Identifier ::= [a-zA-Z_] [a-zA-Z_0-9]*
|
||||
Integer ::= '\d+'
|
||||
Number ::= "-"? Integer ("." Integer)?
|
||||
Boolean ::= "False" | "True"
|
||||
String ::= '(".*?")|(\'.*?\')'
|
||||
None ::= "None"
|
||||
|
||||
Value ::= Number | Boolean | None
|
||||
Literal ::= Number | Boolean | String | None
|
||||
|
||||
UnaryOp ::= "+" | "-" | "!"
|
||||
FactorOp ::= "*" | "/"
|
||||
TermOp ::= "+" | "-"
|
||||
ComparisonOp ::= ">" | "<" | ">=" | "<="
|
||||
EqualityOp ::= "==" | "!="
|
||||
|
||||
Grouping ::= "(" Constraint ")"
|
||||
Primary ::= "_" | Value | Identifier | Grouping
|
||||
PosArg ::= Expression
|
||||
KwArg ::= Identifier "=" Expression
|
||||
|
||||
PosArgs ::= PosArg ("," PosArg)*
|
||||
KwArgs ::= KwArg ("," KwArg)*
|
||||
Args ::= (
|
||||
PosArgs
|
||||
| KwArgs
|
||||
| PosArgs "," KwArgs
|
||||
)
|
||||
|
||||
Grouping ::= "(" Expression ")"
|
||||
Primary ::= "_" | Literal | Identifier | Grouping
|
||||
Reference ::= Primary ("." Identifier)*
|
||||
Unary ::= "-"? Unary | Reference
|
||||
Comparison ::= Unary (ComparisonOp Unary)*
|
||||
CallArgs ::= "(" Args ")"
|
||||
Call ::= Reference CallArgs*
|
||||
Unary ::= UnaryOp Unary | Call
|
||||
Factor ::= Unary (FactorOp Unary)*
|
||||
Term ::= Factor (TermOp Factor)*
|
||||
Comparison ::= Term (ComparisonOp Term)*
|
||||
Equality ::= Comparison (EqualityOp Comparison)*
|
||||
Constraint ::= Equality ("&" Equality)*
|
||||
Expression ::= Equality ("&" Equality)*
|
||||
Constraint ::= Expression
|
||||
|
||||
TemplateParam ::= Identifier ("<:" Type)?
|
||||
Template ::= "[" (TemplateParam ("," TemplateParam)*)? "]"
|
||||
|
||||
ParamType ::= Type "?"?
|
||||
PosParam ::= (Identifier ":")? ParamType
|
||||
KwParam ::= Identifier ":" ParamType
|
||||
|
||||
PosParams ::= (
|
||||
(PosParam ("," PosParam)* ("," "/")?)
|
||||
| "/"
|
||||
)
|
||||
MixedParams ::= KwParam ("," KwParam)
|
||||
KwParams ::= (
|
||||
(("*", ",")? KwParam ("," KwParam)*)
|
||||
| "*"
|
||||
)
|
||||
Params ::= (
|
||||
PosParams
|
||||
| MixedParams
|
||||
| KwParams
|
||||
| (PosParams "," MixedParams)
|
||||
| (PosParams "," KwParams)
|
||||
| (MixedParams "," KwParams)
|
||||
| (PosParams "," MixedParams "," KwParams)
|
||||
)
|
||||
ParamSpec ::= "(" Params? ")"
|
||||
|
||||
TypeProperty ::= Identifier ":" Type
|
||||
ComplexType ::= "{" TypeProperty* "}"
|
||||
NamedType ::= Identifier
|
||||
TypeParams ::= "[" (Type ("," Type)*)? "]"
|
||||
GenericType ::= NamedType TypeParams?
|
||||
TypeArgs ::= "[" (Type ("," Type)*)? "]"
|
||||
FrameColumn ::= TOKEN ":" Type
|
||||
FrameSchema ::= "[" (FrameColumn ("," FrameColumn)*)? "]"
|
||||
GenericType ::= "Frame" FrameSchema | NamedType TypeArgs?
|
||||
GroupedType ::= "(" Type ")"
|
||||
BaseType ::= GroupedType | ComplexType | GenericType
|
||||
BaseType ::= GroupedType | GenericType
|
||||
ConstraintType ::= BaseType ("where" Constraint)?
|
||||
FuncType ::= "fn" ParamSpec "->" Type
|
||||
Type ::= ConstraintType
|
||||
|
||||
OpDefinition ::= "op" Identifier "(" Type ")" "->" Type
|
||||
ExtendBody ::= "{" OpDefinition* "}"
|
||||
MemberStatement ::= ("prop" | "def") Identifier ":" Type
|
||||
ExtendBody ::= "{" MemberStatement* "}"
|
||||
|
||||
AliasStatement ::= "alias" Identifier "=" Type
|
||||
TypeStatement ::= "type" Identifier Template? "=" Type
|
||||
ExtendStatement ::= "extend" Type ExtendBody
|
||||
PredicateStatement ::= "predicate" Identifier "(" Identifier ":" Type ")" "=" Constraint
|
||||
PredicateStatement ::= "predicate" Identifier ParamSpec* "=" Constraint
|
||||
|
||||
Statement ::= TypeStatement | ExtendStatement | PredicateStatement
|
||||
Statement ::= AliasStatement | TypeStatement | ExtendStatement | PredicateStatement
|
||||
|
||||
118
syntax/midas.typ
118
syntax/midas.typ
@@ -7,40 +7,61 @@ svg.railroad .terminal rect {
|
||||
```
|
||||
#let css = default-css() + bytes(extra-css.text)
|
||||
|
||||
#let value = ```
|
||||
{[`value` <
|
||||
#let literal = ```
|
||||
{[`literal` <
|
||||
[`number` 'digit' * ! <!, ["." 'digit' * !]>],
|
||||
[`boolean` <"False", "True">],
|
||||
[`string` <["\"" 'char'*! "\""], ["'" 'char'*! "'"]>],
|
||||
[`none` "None"]
|
||||
>]}
|
||||
```
|
||||
|
||||
#let grouping = ```
|
||||
{[`grouping` "(" 'constraint' ")"]}
|
||||
{[`grouping` "(" 'expression' ")"]}
|
||||
```
|
||||
|
||||
#let primary = ```
|
||||
{[`primary` <"_", 'value', 'identifier', 'grouping'>]}
|
||||
{[`primary` <"_", 'literal', 'identifier', 'grouping'>]}
|
||||
```
|
||||
|
||||
#let reference = ```
|
||||
{[`reference` 'primary' <!, ["." 'identifier']*!>]}
|
||||
```
|
||||
|
||||
#let call-args = ```
|
||||
{[`call-args` "(" <!, <'expression', ['identifier' "=" 'expression']>*","#`Same rules as Python`> ")"]}
|
||||
```
|
||||
|
||||
#let call = ```
|
||||
{[`call` 'reference' <!, 'call-args'*!>]}
|
||||
```
|
||||
|
||||
#let unary = ```
|
||||
{[`unary` <[<!, "-"> 'unary'], 'reference'>]}
|
||||
{[`unary` <[<"+", "-", "!"> 'unary'], 'call'>]}
|
||||
```
|
||||
|
||||
#let factor = ```
|
||||
{[`factor` 'unary'*<"*", "/">]}
|
||||
```
|
||||
|
||||
#let term = ```
|
||||
{[`term` 'factor'*<"+", "-">]}
|
||||
```
|
||||
|
||||
#let comparison = ```
|
||||
{[`comparison` 'unary'*<">", "<", ">=", "<=">]}
|
||||
{[`comparison` 'term'*<">", "<", ">=", "<=">]}
|
||||
```
|
||||
|
||||
#let equality = ```
|
||||
{[`equality` 'comparison'*<"==", "!=">]}
|
||||
```
|
||||
|
||||
#let expression = ```
|
||||
{[`expression` 'equality'*"&"]}
|
||||
```
|
||||
|
||||
#let constraint = ```
|
||||
{[`constraint` 'equality'*"&"]}
|
||||
{[`constraint` 'expression']}
|
||||
```
|
||||
|
||||
#let template-param = ```
|
||||
@@ -51,24 +72,20 @@ svg.railroad .terminal rect {
|
||||
{[`template` "[" <!, 'template-param'*","> "]"]}
|
||||
```
|
||||
|
||||
#let type-property = ```
|
||||
{[`type-property` 'identifier' ":" 'type']}
|
||||
```
|
||||
|
||||
#let complex-type = ```
|
||||
{[`complex-type` "{" <!, 'type-property'*!> "}"]}
|
||||
```
|
||||
|
||||
#let named-type = ```
|
||||
{[`named-type` 'identifier']}
|
||||
```
|
||||
|
||||
#let type-params = ```
|
||||
{[`type-params` "[" <!, 'type'*","> "]"]}
|
||||
#let type-args = ```
|
||||
{[`type-args` "[" <!, 'type'*","> "]"]}
|
||||
```
|
||||
|
||||
#let frame-schema = ```
|
||||
{[`frame-schema` "[" <!, ['TOKEN' ":" 'type']*","> "]"]}
|
||||
```
|
||||
|
||||
#let generic-type = ```
|
||||
{[`generic-type` 'named-type' <!, 'type-params'>]}
|
||||
{[`generic-type` <["Frame" 'frame-schema'], ['named-type' <!, 'type-args'>]>]}
|
||||
```
|
||||
|
||||
#let grouped-type = ```
|
||||
@@ -76,59 +93,88 @@ svg.railroad .terminal rect {
|
||||
```
|
||||
|
||||
#let base-type = ```
|
||||
{[`base-type` <'grouped-type', 'complex-type', 'generic-type'>]}
|
||||
{[`base-type` <'grouped-type', 'generic-type'>]}
|
||||
```
|
||||
|
||||
#let constraint-type = ```
|
||||
{[`constraint-type` 'base-type' <!, ["where" 'constraint']>]}
|
||||
```
|
||||
|
||||
#let pos-param = ```
|
||||
{[`pos-param` <!, ['identifier' ":"]> 'type' <!, "?">]}
|
||||
```
|
||||
|
||||
#let kw-param = ```
|
||||
{[`kw-param` 'identifier' ":" 'type' <!, "?">]}
|
||||
```
|
||||
|
||||
#let param-spec = ```
|
||||
{[`param-spec` "(" <!, <'pos-param', "/", "*", 'kw-param'>*",">#`Same rules as Python` ")"]}
|
||||
```
|
||||
|
||||
#let func-type = ```
|
||||
{[`func-type` "fn" 'param-spec' "->" 'type']}
|
||||
```
|
||||
|
||||
#let type = ```
|
||||
{[`type` 'constraint-type']}
|
||||
{[`type` <'func-type', 'constraint-type'>]}
|
||||
```
|
||||
|
||||
#let alias-statement = ```
|
||||
{[`alias-statement` "alias" 'identifier' "=" 'type']}
|
||||
```
|
||||
|
||||
#let type-statement = ```
|
||||
{[`type-statement` "type" 'identifier' <!, 'template'> "=" 'type']}
|
||||
```
|
||||
|
||||
#let op-definition = ```
|
||||
{[`op-definition` "op" 'identifier' "(" 'type' ")" "->" 'type']}
|
||||
#let member-stmt = ```
|
||||
{[`member-stmt` <"prop", "def"> 'identifier' ":" 'type']}
|
||||
```
|
||||
|
||||
#let extend-statement = ```
|
||||
{[`extend-statement` "extend" 'type' "{" <!, 'op-definition'*!> "}"]}
|
||||
{[`extend-statement` "extend" 'type' "{" <!, 'member-stmt'*!> "}"]}
|
||||
```
|
||||
|
||||
#let predicate-statement = ```
|
||||
{[`predicate-statement` "predicate" 'identifier' "(" 'identifier' ":" 'type' ")" "=" 'constraint']}
|
||||
{[`predicate-statement` "predicate" 'identifier' <!, 'param-spec'*!> "=" 'constraint']}
|
||||
```
|
||||
|
||||
#let statement = ```
|
||||
{[`statement` <'type-statement', 'extend-statement', 'predicate-statement'>]}
|
||||
{[`statement` <'alias-statement', 'type-statement', 'extend-statement', 'predicate-statement'>]}
|
||||
```
|
||||
|
||||
#let rules = (
|
||||
value: value,
|
||||
literal: literal,
|
||||
grouping: grouping,
|
||||
primary: primary,
|
||||
reference: reference,
|
||||
call-args: call-args,
|
||||
call: call,
|
||||
unary: unary,
|
||||
factor: factor,
|
||||
term: term,
|
||||
comparison: comparison,
|
||||
equality: equality,
|
||||
expression: expression,
|
||||
constraint: constraint,
|
||||
template-param: template-param,
|
||||
template: template,
|
||||
type-property: type-property,
|
||||
complex-type: complex-type,
|
||||
named-type: named-type,
|
||||
type-params: type-params,
|
||||
type-args: type-args,
|
||||
generic-type: generic-type,
|
||||
grouped-type: grouped-type,
|
||||
base-type: base-type,
|
||||
constraint-type: constraint-type,
|
||||
pos-param: pos-param,
|
||||
kw-param: kw-param,
|
||||
param-spec: param-spec,
|
||||
func-type: func-type,
|
||||
type: type,
|
||||
alias-statement: alias-statement,
|
||||
type-statement: type-statement,
|
||||
op-definition: op-definition,
|
||||
member-stmt: member-stmt,
|
||||
extend-statement: extend-statement,
|
||||
predicate-statement: predicate-statement,
|
||||
statement: statement,
|
||||
@@ -136,18 +182,22 @@ svg.railroad .terminal rect {
|
||||
|
||||
#let inline = (
|
||||
"grouping",
|
||||
"value",
|
||||
"literal",
|
||||
"template-param",
|
||||
"template",
|
||||
"type-property",
|
||||
"complex-type",
|
||||
"type-params",
|
||||
"call-args",
|
||||
"type-args",
|
||||
"named-type",
|
||||
"grouped-type",
|
||||
"generic-type",
|
||||
"base-type",
|
||||
"constraint-type",
|
||||
"op-definition",
|
||||
"pos-param",
|
||||
"kw-param",
|
||||
"func-type",
|
||||
"member-stmt",
|
||||
"alias-statement",
|
||||
"type-statement",
|
||||
"extend-statement",
|
||||
"predicate-statement",
|
||||
@@ -164,7 +214,7 @@ svg.railroad .terminal rect {
|
||||
2,
|
||||
outline(title: none),
|
||||
),
|
||||
height: 9cm,
|
||||
height: 15cm,
|
||||
stroke: 1pt,
|
||||
inset: 1em,
|
||||
)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# type: ignore
|
||||
# ruff: disable [F821]
|
||||
|
||||
df1: Frame[a:int, b:float]
|
||||
df2: Frame[a:int, b:float]
|
||||
df1: Frame[i:int, a:int, b:float]
|
||||
df2: Frame[i:int, a:int, b:float]
|
||||
|
||||
_: Any
|
||||
|
||||
@@ -38,7 +38,7 @@ _ = df1.sum()
|
||||
_ = df1.var()
|
||||
|
||||
# Groupby
|
||||
df_gb = df1.groupby(by="a")
|
||||
df_gb = df1.groupby(by="i")
|
||||
|
||||
_ = df_gb.kurt()
|
||||
_ = df_gb.max()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,26 +9,22 @@ type Longitude = float where (-180 <= _ <= 180)
|
||||
type Difference[T] = T
|
||||
|
||||
// Complex custom type, containing two values accessible through properties
|
||||
type GeoLocation = {
|
||||
type GeoLocation = object
|
||||
|
||||
extend GeoLocation {
|
||||
prop lat: Latitude
|
||||
prop lon: Longitude
|
||||
}
|
||||
|
||||
// Define operations on our custom type
|
||||
extend GeoLocation {
|
||||
// This type is compatible with the `-` operation with another GeoLocation
|
||||
// i.e. you can subtract a GeoLocation from another GeoLocation, resulting
|
||||
// in a Difference of GeoLocations
|
||||
def __sub__: fn(GeoLocation, /) -> Difference[GeoLocation]
|
||||
}
|
||||
type GeoLocationDifference = object
|
||||
|
||||
// For complex generics, you need to specify how the genericity the properties
|
||||
// are handled
|
||||
type Difference[GeoLocation] = {
|
||||
extend GeoLocationDifference {
|
||||
prop lat: Difference[Latitude]
|
||||
prop lon: Difference[Longitude]
|
||||
}
|
||||
|
||||
// Define operations on our custom type
|
||||
|
||||
// Simple operation defined on our custom types
|
||||
extend Latitude {
|
||||
def __sub__: fn(Latitude, /) -> Difference[Latitude]
|
||||
@@ -38,13 +34,23 @@ extend Longitude {
|
||||
def __sub__: fn(Longitude, /) -> Difference[Longitude]
|
||||
}
|
||||
|
||||
extend GeoLocation {
|
||||
// This type is compatible with the `-` operation with another GeoLocation
|
||||
// i.e. you can subtract a GeoLocation from another GeoLocation, resulting
|
||||
// in a GeoLocationDifference
|
||||
def __sub__: fn(GeoLocation, /) -> GeoLocationDifference
|
||||
}
|
||||
|
||||
|
||||
// Predefined custom predicates that can be referenced in other definitions
|
||||
predicate Positive(v: float) = v >= 0
|
||||
predicate StrictlyPositive(v: float) = v > 0
|
||||
predicate Equatorial(loc: GeoLocation) = (-10 <= loc.lat <= 10)
|
||||
predicate Arctic(loc: GeoLocation) = (loc.lat >= 66)
|
||||
|
||||
type Person = {
|
||||
type Person = object
|
||||
|
||||
extend Person {
|
||||
prop name: str
|
||||
|
||||
// Property with an inline constraint
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,11 +4,9 @@ from midas.ast.midas import (
|
||||
AliasStmt,
|
||||
BinaryExpr,
|
||||
CallExpr,
|
||||
ComplexType,
|
||||
ConstraintType,
|
||||
Expr,
|
||||
ExtendStmt,
|
||||
ExtensionType,
|
||||
FrameType,
|
||||
FunctionType,
|
||||
GenericType,
|
||||
@@ -172,12 +170,6 @@ class MidasAstJsonSerializer(
|
||||
"constraint": type.constraint.accept(self),
|
||||
}
|
||||
|
||||
def visit_complex_type(self, type: ComplexType) -> dict:
|
||||
return {
|
||||
"_type": "ComplexType",
|
||||
"members": self._serialize_list(type.members),
|
||||
}
|
||||
|
||||
def visit_function_type(self, type: FunctionType) -> dict:
|
||||
return {
|
||||
"_type": "FunctionType",
|
||||
@@ -200,13 +192,6 @@ class MidasAstJsonSerializer(
|
||||
"required": param.required,
|
||||
}
|
||||
|
||||
def visit_extension_type(self, type: ExtensionType) -> dict:
|
||||
return {
|
||||
"_type": "ExtensionType",
|
||||
"base": type.base.accept(self),
|
||||
"extension": type.extension.accept(self),
|
||||
}
|
||||
|
||||
def visit_frame_type(self, type: FrameType) -> dict:
|
||||
return {
|
||||
"_type": "FrameType",
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
{
|
||||
"brackets": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["<", ">"]
|
||||
["[", "]"]
|
||||
],
|
||||
"autoClosingPairs": [
|
||||
{ "open": "{", "close": "}" },
|
||||
{ "open": "[", "close": "]" },
|
||||
{ "open": "(", "close": ")" },
|
||||
{ "open": "<", "close": ">" }
|
||||
{ "open": "(", "close": ")" }
|
||||
],
|
||||
"surroundingPairs": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"],
|
||||
["<", ">"]
|
||||
["(", ")"]
|
||||
]
|
||||
}
|
||||
@@ -10,7 +10,6 @@
|
||||
{
|
||||
"id": "midas",
|
||||
"extensions": [
|
||||
".mpy",
|
||||
".midas"
|
||||
],
|
||||
"aliases": [
|
||||
@@ -23,10 +22,7 @@
|
||||
{
|
||||
"language": "midas",
|
||||
"scopeName": "source.midas",
|
||||
"path": "./syntaxes/midas.tmLanguage.json",
|
||||
"embeddedLanguages": {
|
||||
"meta.embedded.block.python": "python"
|
||||
}
|
||||
"path": "./syntaxes/midas.tmLanguage.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,167 +2,558 @@
|
||||
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
|
||||
"name": "Midas",
|
||||
"scopeName": "source.midas",
|
||||
"patterns": [{ "include": "#statement" }],
|
||||
"fileTypes": [
|
||||
"midas"
|
||||
],
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"include": "#alias-stmt"
|
||||
},
|
||||
{
|
||||
"include": "#type-stmt"
|
||||
},
|
||||
{
|
||||
"include": "#extend-stmt"
|
||||
},
|
||||
{
|
||||
"include": "#extend-body"
|
||||
},
|
||||
{
|
||||
"include": "#predicate-stmt"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"comment": {
|
||||
"begin": "(//)",
|
||||
"end": "($)",
|
||||
"name": "comment.line",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "comment.line.double-dash"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type-def": {
|
||||
"begin": "\\b(type)\\s+([a-zA-Z_][a-zA-Z_\\d]*)",
|
||||
"end": "$",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.control.type.midas"
|
||||
},
|
||||
"2": {
|
||||
"name" : "variable.name"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"patterns": [
|
||||
{ "include": "#type-base" },
|
||||
{ "include": "#type-body" }
|
||||
{
|
||||
"begin": "//",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.comment.midas"
|
||||
}
|
||||
},
|
||||
"end": "$",
|
||||
"name": "comment.line.double-slash.midas"
|
||||
},
|
||||
{
|
||||
"begin": "/\\*",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.comment.midas"
|
||||
}
|
||||
},
|
||||
"end": "\\*/",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.comment.midas"
|
||||
}
|
||||
},
|
||||
"name": "comment.block.midas"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type-base": {
|
||||
"begin": "(\\()([a-zA-Z_][a-zA-Z_\\d]*)(\\))",
|
||||
"end": "$",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.base.begin.midas"
|
||||
},
|
||||
"2": {
|
||||
"name": "variable.name"
|
||||
},
|
||||
"3": {
|
||||
"name": "punctuation.definition.base.end.midas"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{ "include": "#type-cond" }
|
||||
]
|
||||
},
|
||||
"type-cond": {
|
||||
"begin": "where",
|
||||
"end": "$",
|
||||
"string": {
|
||||
"begin": "\"",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "keyword.control.where.midas"
|
||||
"name": "punctuation.definition.string.begin.midas"
|
||||
}
|
||||
}
|
||||
},
|
||||
"end": "\"",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.end.midas"
|
||||
}
|
||||
},
|
||||
"name": "string.quoted.double.c"
|
||||
},
|
||||
"type-body": {
|
||||
"alias-stmt": {
|
||||
"begin": "\\b(alias)\\b",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.declaration.midas"
|
||||
}
|
||||
},
|
||||
"end": "$",
|
||||
"name": "meta.declaration.alias.midas",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"match": "[A-Za-z_][A-Za-z0-9_]*",
|
||||
"name": "entity.name.type.midas"
|
||||
},
|
||||
{
|
||||
"begin": "=",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "keyword.operator.equal.midas"
|
||||
}
|
||||
},
|
||||
"end": "$",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#type-expr"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"type-stmt": {
|
||||
"begin": "\\b(type)\\b",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.declaration.midas"
|
||||
}
|
||||
},
|
||||
"end": "$",
|
||||
"name": "meta.declaration.type.midas",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"match": "[A-Za-z_][A-Za-z0-9_]*",
|
||||
"name": "entity.name.type.midas"
|
||||
},
|
||||
{
|
||||
"begin": "\\[",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.brackets.begin.midas"
|
||||
}
|
||||
},
|
||||
"end": "\\]",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.brackets.end.midas"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"include": "#type-params"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "=",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "keyword.operator.equal.midas"
|
||||
}
|
||||
},
|
||||
"end": "$",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#type-expr"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"type-params": {
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"match": "<:",
|
||||
"name": "keyword.operator.subtype.midas"
|
||||
},
|
||||
{
|
||||
"match": "[A-Za-z][A-Za-z0-9_]*",
|
||||
"name": "entity.name.type.midas"
|
||||
}
|
||||
]
|
||||
},
|
||||
"extend-stmt": {
|
||||
"begin": "\\b(extend)\\b",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.declaration.midas"
|
||||
}
|
||||
},
|
||||
"end": "(?=\\{)|$",
|
||||
"name": "meta.declaration.extend.midas",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"match": "[A-Za-z_][A-Za-z0-9_]*",
|
||||
"name": "entity.name.type.midas"
|
||||
},
|
||||
{
|
||||
"begin": "\\[",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.brackets.begin.midas"
|
||||
}
|
||||
},
|
||||
"end": "\\]",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.brackets.end.midas"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"include": "#type-params"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"extend-body": {
|
||||
"begin": "\\{",
|
||||
"end": "\\}",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.type-body.begin.midas"
|
||||
"name": "punctuation.section.block.begin.midas"
|
||||
}
|
||||
},
|
||||
"end": "\\}",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.type-body.end.midas"
|
||||
"name": "punctuation.section.block.end.midas"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{"include": "#type-prop"},
|
||||
{"include": "#comment"}
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"include": "#member-stmt"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type-prop": {
|
||||
"match": "([a-zA-Z_][a-zA-Z_\\d]*)(:)\\s*([a-zA-Z_][a-zA-Z_\\d]*)",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "variable.name"
|
||||
"member-stmt": {
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
"2": {
|
||||
"name": "punctuation.separator.annotation.midas"
|
||||
},
|
||||
"3": {
|
||||
"name": "meta.type.name"
|
||||
{
|
||||
"begin": "\\b(prop|def)\\b",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.other.midas"
|
||||
}
|
||||
},
|
||||
"end": "$",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"match": "[A-Za-z_][A-Za-z0-9_]*",
|
||||
"name": "variable.other.member.midas"
|
||||
},
|
||||
{
|
||||
"begin": ":",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.separator.annotation.midas"
|
||||
}
|
||||
},
|
||||
"end": "$",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#type-expr"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"extend-def": {
|
||||
"begin": "\\b(extend)\\s*([a-zA-Z_][a-zA-Z_\\d]*)\\s+(\\{)",
|
||||
"end": "\\}",
|
||||
"predicate-stmt": {
|
||||
"begin": "\\b(predicate)\\b",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.control.extend.midas"
|
||||
},
|
||||
"2": {
|
||||
"name": "variable.name"
|
||||
},
|
||||
"3": {
|
||||
"name": "punctuation.definition.extend-body.begin.midas"
|
||||
"name": "keyword.declaration.midas"
|
||||
}
|
||||
},
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.extend-body.end.midas"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{"include": "#op-def"},
|
||||
{"include": "#comment"}
|
||||
]
|
||||
},
|
||||
"op-def": {
|
||||
"match": "\\b(op)\\s+(\\S+)\\s*\\(\\s*([a-zA-Z_][a-zA-Z_\\d]*)\\s*\\)\\s*(->)\\s*([a-zA-Z_][a-zA-Z_\\d]*)",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "keyword.control.op.midas"
|
||||
},
|
||||
"2": {
|
||||
"name" : "keyword.operator"
|
||||
},
|
||||
"3": {
|
||||
"name" : "variable.name"
|
||||
},
|
||||
"4": {
|
||||
"name" : "keyword.operator.assignment"
|
||||
},
|
||||
"5": {
|
||||
"name" : "variable.name"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pred-def": {
|
||||
"begin": "(predicate)\\s+([a-zA-Z_][a-zA-Z_\\d]*)\\(([a-zA-Z_][a-zA-Z_\\d]*):\\s*([a-zA-Z_][a-zA-Z_\\d]*)\\)\\s*(=)",
|
||||
"end": "$",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.control.pred.midas"
|
||||
},
|
||||
"2": {
|
||||
"name": "variable.name"
|
||||
},
|
||||
"3": {
|
||||
"name": "variable.name"
|
||||
},
|
||||
"4": {
|
||||
"name": "variable.name"
|
||||
},
|
||||
"5": {
|
||||
"name": "keyword.operator.assignment"
|
||||
}
|
||||
},
|
||||
"name": "meta.declaration.predicate.midas",
|
||||
"patterns": [
|
||||
{ "include": "source.python" }
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"match": "[A-Za-z_][A-Za-z0-9_]*",
|
||||
"name": "entity.name.function.midas"
|
||||
},
|
||||
{
|
||||
"begin": "\\(",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.group.begin.midas"
|
||||
}
|
||||
},
|
||||
"end": "\\)",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.group.end.midas"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#predicate-params"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "=",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "keyword.operator.equal.midas"
|
||||
}
|
||||
},
|
||||
"end": "$",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#constraint"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"statement": {
|
||||
"predicate-params": {
|
||||
"patterns": [
|
||||
{ "include": "#comment" },
|
||||
{ "include": "#type-def" },
|
||||
{ "include": "#extend-def" },
|
||||
{ "include": "#pred-def" }
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"begin": "([A-Za-z_][A-Za-z0-9_]*)(:)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "variable.parameter.midas"
|
||||
},
|
||||
"2": {
|
||||
"name": "punctuation.separator.annotation.midas"
|
||||
}
|
||||
},
|
||||
"end": "(?=,)|(?=\\))",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#type-expr"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": ",",
|
||||
"name": "punctuation.separator.midas"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type-expr": {
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"begin": "\\b(fn)\\s*(\\()",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.other.midas"
|
||||
},
|
||||
"2": {
|
||||
"name": "punctuation.section.group.begin.midas"
|
||||
}
|
||||
},
|
||||
"end": "\\)",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.group.end.midas"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#fn-params"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": "->",
|
||||
"name": "keyword.operator.arrow.midas"
|
||||
},
|
||||
{
|
||||
"begin": "\\b(where)\\b",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.other.midas"
|
||||
}
|
||||
},
|
||||
"end": "$",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#constraint"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "(\\bFrame\\b)(\\s*)(\\[)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "entity.name.type.midas"
|
||||
},
|
||||
"3": {
|
||||
"name": "punctuation.section.brackets.begin.midas"
|
||||
}
|
||||
},
|
||||
"end": "\\]",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.brackets.end.midas"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#frame-schema"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": "\\bFrame\\b",
|
||||
"name": "entity.name.type.midas"
|
||||
},
|
||||
{
|
||||
"match": "[A-Za-z_][A-Za-z0-9_]*",
|
||||
"name": "entity.name.type.midas"
|
||||
},
|
||||
{
|
||||
"begin": "\\[",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.brackets.begin.midas"
|
||||
}
|
||||
},
|
||||
"end": "\\]",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.brackets.end.midas"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"include": "#type-expr"
|
||||
},
|
||||
{
|
||||
"match": ",",
|
||||
"name": "punctuation.separator.midas"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"fn-params": {
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"begin": "([A-Za-z_][A-Za-z0-9_]*)(:)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "variable.parameter.midas"
|
||||
},
|
||||
"2": {
|
||||
"name": "punctuation.separator.annotation.midas"
|
||||
}
|
||||
},
|
||||
"end": "(?=,)|(?=\\))",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#type-expr"
|
||||
},
|
||||
{
|
||||
"match": "\\?",
|
||||
"name": "keyword.operator.qmark.midas"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": ",",
|
||||
"name": "punctuation.separator.midas"
|
||||
},
|
||||
{
|
||||
"include": "#type-expr"
|
||||
}
|
||||
]
|
||||
},
|
||||
"constraint": {
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"match": "\\d+(\\.\\d+)?",
|
||||
"name": "constant.numeric.midas"
|
||||
},
|
||||
{
|
||||
"match": "\\b(true|false|none)\\b",
|
||||
"name": "constant.language.midas"
|
||||
},
|
||||
{
|
||||
"include": "#string"
|
||||
},
|
||||
{
|
||||
"match": "(<=|>=|<|>|==|!=|&)",
|
||||
"name": "keyword.operator.midas"
|
||||
},
|
||||
{
|
||||
"match": "_",
|
||||
"name": "variable.language.midas"
|
||||
},
|
||||
{
|
||||
"match": "[A-Za-z_][A-Za-z0-9_]*(?=\\s*\\()",
|
||||
"name": "variable.function.midas"
|
||||
},
|
||||
{
|
||||
"match": "[A-Za-z_][A-Za-z0-9_]*",
|
||||
"name": "variable.other.readwrite.midas"
|
||||
}
|
||||
]
|
||||
},
|
||||
"frame-schema": {
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"match": "[A-Za-z_][A-Za-z0-9_]*",
|
||||
"name": "variable.other.member.midas"
|
||||
},
|
||||
{
|
||||
"begin": ":",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.separator.annotation.midas"
|
||||
}
|
||||
},
|
||||
"end": "(?=,)|(?=\\])",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#type-expr"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": ",",
|
||||
"name": "punctuation.separator.midas"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user