Compile the DSL to python lambdas instead of using an IR interpreter
This commit is contained in:
parent
f7d712437e
commit
258a578cb7
|
@ -1,7 +1,7 @@
|
||||||
import datetime
|
import datetime
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
from . import check_date
|
from . import dsl
|
||||||
from . import daterange
|
from . import daterange
|
||||||
from . import generate_timetable
|
from . import generate_timetable
|
||||||
from . import parse_coursefile
|
from . import parse_coursefile
|
||||||
|
@ -37,7 +37,7 @@ def main():
|
||||||
|
|
||||||
courses = []
|
courses = []
|
||||||
for name, info, parsed_filter in courses_parsed:
|
for name, info, parsed_filter in courses_parsed:
|
||||||
date_filter = check_date.compile(parsed_filter)
|
date_filter = dsl.compile(parsed_filter)
|
||||||
courses.append((name, info, date_filter))
|
courses.append((name, info, date_filter))
|
||||||
|
|
||||||
timetable = generate_timetable.generate_timetable(dates, courses)
|
timetable = generate_timetable.generate_timetable(dates, courses)
|
||||||
|
|
|
@ -7,7 +7,7 @@ class Filters(enum.Enum):
|
||||||
class Conjunctions(enum.Enum):
|
class Conjunctions(enum.Enum):
|
||||||
all, any, none, implies = range(4)
|
all, any, none, implies = range(4)
|
||||||
|
|
||||||
def compile(parsed):
|
def to_ir(parsed):
|
||||||
assert(len(parsed) >= 1)
|
assert(len(parsed) >= 1)
|
||||||
function, *parameters = parsed
|
function, *parameters = parsed
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ def compile(parsed):
|
||||||
|
|
||||||
elif function == 'week':
|
elif function == 'week':
|
||||||
if len(parameters) > 1:
|
if len(parameters) > 1:
|
||||||
return (Conjunctions.any,) + tuple([compile(('week', week)) for week in parameters])
|
return (Conjunctions.any,) + tuple([to_ir(('week', week)) for week in parameters])
|
||||||
else:
|
else:
|
||||||
assert(len(parameters) == 1)
|
assert(len(parameters) == 1)
|
||||||
week_data, = parameters
|
week_data, = parameters
|
||||||
|
@ -37,7 +37,7 @@ def compile(parsed):
|
||||||
|
|
||||||
elif function == 'weekday':
|
elif function == 'weekday':
|
||||||
if len(parameters) > 1:
|
if len(parameters) > 1:
|
||||||
return (Conjunctions.any,) + tuple([compile(('weekday', weekday)) for weekday in parameters])
|
return (Conjunctions.any,) + tuple([to_ir(('weekday', weekday)) for weekday in parameters])
|
||||||
else:
|
else:
|
||||||
assert(len(parameters) == 1)
|
assert(len(parameters) == 1)
|
||||||
weekday, = parameters
|
weekday, = parameters
|
||||||
|
@ -45,50 +45,51 @@ def compile(parsed):
|
||||||
return (Filters.is_weekday, weekday)
|
return (Filters.is_weekday, weekday)
|
||||||
|
|
||||||
elif function == 'and':
|
elif function == 'and':
|
||||||
return (Conjunctions.all,) + tuple([compile(parameter) for parameter in parameters])
|
return (Conjunctions.all,) + tuple([to_ir(parameter) for parameter in parameters])
|
||||||
|
|
||||||
elif function == 'or':
|
elif function == 'or':
|
||||||
return (Conjunctions.any,) + tuple([compile(parameter) for parameter in parameters])
|
return (Conjunctions.any,) + tuple([to_ir(parameter) for parameter in parameters])
|
||||||
|
|
||||||
elif function == 'not':
|
elif function == 'not':
|
||||||
return (Conjunctions.none,) + tuple([compile(parameter) for parameter in parameters])
|
return (Conjunctions.none,) + tuple([to_ir(parameter) for parameter in parameters])
|
||||||
|
|
||||||
elif function == 'if':
|
elif function == 'if':
|
||||||
assert(len(parameters) == 2)
|
assert(len(parameters) == 2)
|
||||||
condition, then = parameters
|
condition, then = parameters
|
||||||
return (Conjunctions.implies, compile(condition), compile(then))
|
return (Conjunctions.implies, to_ir(condition), to_ir(then))
|
||||||
|
|
||||||
def check_day_match(day, date_filter):
|
def to_lambda(date_filter):
|
||||||
assert(len(date_filter) >= 1)
|
assert(len(date_filter) >= 1)
|
||||||
function, *parameters = date_filter
|
function, *parameters = date_filter
|
||||||
|
|
||||||
assert(function in Filters or function in Conjunctions)
|
assert(function in Filters or function in Conjunctions)
|
||||||
if function == Conjunctions.implies:
|
|
||||||
assert(len(parameters) == 2)
|
|
||||||
elif function in [Filters.in_date_range, Filters.is_weekday]:
|
|
||||||
assert(len(parameters) == 1)
|
|
||||||
else:
|
|
||||||
assert(function in [Conjunctions.all, Conjunctions.any, Conjunctions.none])
|
|
||||||
|
|
||||||
if function == Conjunctions.all:
|
if function == Conjunctions.all:
|
||||||
return all(map(lambda parameter: check_day_match(day, parameter), parameters))
|
compiled = [to_lambda(parameter) for parameter in parameters]
|
||||||
|
return lambda day: all(map(lambda f: f(day), compiled))
|
||||||
|
|
||||||
elif function == Conjunctions.any:
|
elif function == Conjunctions.any:
|
||||||
return any(map(lambda parameter: check_day_match(day, parameter), parameters))
|
compiled = [to_lambda(parameter) for parameter in parameters]
|
||||||
|
return lambda day: any(map(lambda f: f(day), compiled))
|
||||||
|
|
||||||
elif function == Conjunctions.implies:
|
elif function == Conjunctions.implies:
|
||||||
left, right = parameters
|
assert(len(parameters) == 2)
|
||||||
left_truth = check_day_match(day, left)
|
left, right = to_lambda(parameters[0], parameters[1])
|
||||||
right_truth = check_day_match(day, right)
|
return lambda day: right(day) if left(day) else True
|
||||||
return left_truth and right_truth or not left_truth
|
|
||||||
|
|
||||||
elif function == Conjunctions.none:
|
elif function == Conjunctions.none:
|
||||||
return not any(map(lambda parameter: check_day_match(day, parameter), parameters))
|
compiled = [to_lambda(parameter) for parameter in parameters]
|
||||||
|
return lambda day: not any(map(lambda f: f(day), compiled))
|
||||||
|
|
||||||
elif function == Filters.in_date_range:
|
elif function == Filters.in_date_range:
|
||||||
|
assert(len(parameters) == 1)
|
||||||
date_range, = parameters
|
date_range, = parameters
|
||||||
return day in date_range
|
return lambda day: day in date_range
|
||||||
|
|
||||||
elif function == Filters.is_weekday:
|
elif function == Filters.is_weekday:
|
||||||
|
assert(len(parameters) == 1)
|
||||||
weekday, = parameters
|
weekday, = parameters
|
||||||
return day.isoweekday() == weekday
|
return lambda day: day.isoweekday() == weekday
|
||||||
|
|
||||||
|
def compile(parsed):
|
||||||
|
ir = to_ir(parsed)
|
||||||
|
return to_lambda(ir)
|
|
@ -1,5 +1,4 @@
|
||||||
import datetime
|
import datetime
|
||||||
from . import check_date
|
|
||||||
|
|
||||||
def generate_timetable(day_range, courses):
|
def generate_timetable(day_range, courses):
|
||||||
start_date, end_date = day_range.range()
|
start_date, end_date = day_range.range()
|
||||||
|
@ -7,7 +6,7 @@ def generate_timetable(day_range, courses):
|
||||||
appointments = []
|
appointments = []
|
||||||
while True:
|
while True:
|
||||||
for name, info, date_filter in courses:
|
for name, info, date_filter in courses:
|
||||||
if check_date.check_day_match(date, date_filter):
|
if date_filter(date):
|
||||||
appointments.append((date, name, info))
|
appointments.append((date, name, info))
|
||||||
|
|
||||||
if date == end_date:
|
if date == end_date:
|
||||||
|
|
Loading…
Reference in New Issue