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

[WIP] Generalized Mad-X Parser #268

Draft
wants to merge 15 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/madx/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# MadX Python Interpreter (10/4/22)

Author: Joey Zhu (https://github.com/np-eazy)

This Python interpreter was written as a subset of MadX's C interpreter's full functionalities to suit the needs of ImpactX.
Implementation contains a lot of boilerplate, but this is to maintain a reliable, verbatim approach for transcribing a large
volume of code.

### Supported objects
- Variables
- Elements
- Macros (Lines)

### Removed/Changed Functionalities
- stdin stdout char buffers are replaced with Python file read
- Removed Fortran90 interface

### Other dev notes
- Execution begins at mad_main.py
3 changes: 3 additions & 0 deletions src/madx/interpreter/mad_eval.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def pro_input(file_content, i):
# TODO: This is where the parsing logic starts!!!
return None
166 changes: 166 additions & 0 deletions src/madx/mad_core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# include <signal.h>
# include "madx.h"

from src.madx.interpreter.mad_eval import *
from src.madx.objects.mad_cmd import *
from src.madx.objects.mad_elem import *
from src.madx.objects.mad_macro import *
from src.madx.objects.mad_var import *
from src.madx.utils.mad_str import *


def mad_init_c(gvar):
# allocate variable ptr
ione = 1

# make stdout unbuffered for proper I/O synchronization with fortran
# setvbuf(stdout, 0, _IONBF, 0);
#
# init55(123456789); /* random generator */
# if (watch_flag == 1) debug_file = fopen("madx.debug", "w");
# else if (watch_flag == 2) debug_file = stdout;
# if (stamp_flag == 1) stamp_file = fopen("madx.stamp", "w");
# else if (stamp_flag == 2) stamp_file = stdout;

# in = new_in_buff_list(100); /* list of input buffers, dynamic */

# // quick and dirty fix to accept jobs from filename
# in->input_files[0] = mad_argc > 1 ? fopen(mad_argv[1], "r") : stdin;
# if (!in->input_files[0]) {
# mad_error("invalid input filename ", " %s", mad_argv[1]);
# in->input_files[0] = stdin;
# }
# interactive = intrac();
# prt_file = stdout;
# pro = new_in_buff_list(100); /* list of process buffers, dynamic */
# pro->buffers[0] = new_in_buffer(IN_BUFF_SIZE);
# pro->curr = 1;
# c_dum = new_char_array(AUX_LG);
# c_join = new_char_array(AUX_LG);
# work = new_char_array(AUX_LG);
# l_wrk = new_char_array(AUX_LG);

# Physical Constants:
# deco_init();
# get_defined_constants();
# get_defined_commands(command_def);
# get_defined_commands(element_def);
# get_sxf_names();
#
# pi = get_variable("pi");
# twopi = two * pi;
# degrad = 180 / pi;
# raddeg = pi / 180;
# e = get_variable("e");
# clight = get_variable("clight");
# hbar = get_variable("hbar");

# Global Variable Initialization:
# aux_buff = new_char_array(AUX_LG); /* dynamic temporary buffer */
gvar.variable_list = new_var_list(2000) # dynamic list of variables
gvar.beam_list = new_command_list("beam_list", 10) # dynamic beam list
gvar.table_deselect = new_command_list_list(10) # dynamic
gvar.table_select = new_command_list_list(10) # dynamic
gvar.defined_commands = new_command_list("defined_commands", 100) # dynamic
gvar.stored_commands = new_command_list("stored_commands", 500) # dynamic
gvar.line_list = new_macro_list(100) # dynamic
gvar.macro_list = new_macro_list(100) # dynamic
gvar.base_type_list = new_el_list(60) # dynamic
gvar.element_list = new_el_list(20000) # dynamic
# buffered_cmds = new_in_cmd_list(10000); /* dynamic */
# sequences = new_sequence_list(20); /* dynamic */
# match_sequs = new_sequence_list(2);
# selected_ranges = new_node_list(10000); /* dynamic */
gvar.selected_elements = new_el_list(10000) # dynamic
# tmp_p_array = new_char_p_array(1000); /* dynamic */
# tmp_l_array = new_char_p_array(1000); /* dynamic */
# sxf_list = new_name_list("sxf_list", 50); /* dynamic */
# all_table_lists = new_table_list_list(10); /* dynamic */

# # Initialize needed work for commands
var = new_variable("twiss_tol", 1.0e-6, 1, 1, None, None)
add_to_var_list(var, gvar.variable_list, 1)
# title = permbuff("no-title");
# set_defaults("option");
# if (interactive) { int false = 0; set_option("echo", &false); }
# set_defaults("beam");
# add_to_command_list("default_beam", current_beam, beam_list, 0);
# set_defaults("set");
# set_defaults("setplot");
# set_defaults("threader");
# table_register = new_table_list(10); /* dynamic */
# beta0_list = new_command_list("beta0_list", 10); /* dynamic */
# savebeta_list = new_command_list("savebeta_list", 10); /* dynamic */
# seqedit_select = /* dynamic - for "select seqedit" commands */
# new_command_list("seqedit_select", 10);
# error_select = /* dynamic - for "select error" commands */
# new_command_list("error-select", 10);
# save_select = /* dynamic - for "select save" commands */
# new_command_list("save_select", 10);
# slice_select = /* dynamic - for "select makethin" commands */
# new_command_list("slice_select", 10);
# sector_select = /* dynamic - for "select sectormap" commands */
# new_command_list("sector_select", 10);
# interp_select = /* dynamic - for "select sectormap" commands */
# new_command_list("interp_select", 10);
# s_range = new_int_array(10); /* dynamic */
# e_range = new_int_array(10); /* dynamic */
# sd_range = new_int_array(10); /* dynamic */
# ed_range = new_int_array(10); /* dynamic */
# zero_double(orbit0, 6);
# zero_double(disp0, 6);
# zero_double(guess_orbit,6);
# zero_double(oneturnmat, 36);
# set_option("twiss_print", &ione);
return None


def madx_start(gvar):

mad_init_c(gvar)

return None


def madx_input(filename, gvar):

# The original MadX file uses charbuffers, but in the Python version we want to keep
# implementation simple with filenames and char lists, and whatever equivalent looping
# logic. We assume that given ImpactX's use case, there is only one case for the input:
# That is, anything and everything is in file_content, so we don't have to do any buffer logic.
file_content = []
with open(filename, "r") as f:
file_content += [f.read()]
i = 0
in_stop = False
while not in_stop:
# TODO: Implement dynamic metadata lists
# We don't need line numbers per se, just the order of buffer consumption is enough for metadata.
stolower_nq(file_content, i)

# TODO: Figure out exactly where pro_input is defined. This is the entry point into the interpreter logic but
# isn't clearly defined in the source code.
pro_input(file_content, i)
if gvar.stop_flag:
return

in_stop = i < len(file_content)
i += 1 # whenever a buffer char is popped for interpreter

return None


def madx_finish(gvar):
for variable in gvar.variable_list:
# TODO: Convert variable into ImpactX known type and add to other lists
variable = variable

for element in gvar.el_list:
# TODO: Convert element into ImpactX known type and add to other lists
element = element

for line in gvar.line_list:
# TODO: Convert line into ImpactX known type and add to other lists
line = line

return None
21 changes: 21 additions & 0 deletions src/madx/mad_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from mad_core import *

from src.madx.objects import mad_gvar


def mad_init(gvar):
madx_start(gvar)


def mad_run(gvar, file=0):
madx_input(file, gvar)


def mad_finish(gvar):
madx_finish(gvar)


global_variable = mad_gvar.GlobalVariable()
mad_init(global_variable)
mad_run(global_variable)
mad_finish(global_variable)
126 changes: 126 additions & 0 deletions src/madx/objects/mad_cmd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# TODO: Implement on-demand
class Command:
def __init__(
self, name, module, group, stamp, link_type, mad8_type, beam_def, par_names, par
):
self.name = name
self.module = module
self.group = group
self.stamp = stamp
self.link_type = link_type
self.mad8_type = mad8_type
self.beam_def = beam_def
self.par_names = par_names
self.par = par


class CommandList:
def __init__(self, name, max_length):
self.name = name
self.lst = []
self.names = []
self.max_length = max_length

def add_var(self, var):
self.lst += [var]


class CommandListList:
def __init__(self, max_length):
self.lst = []
self.names = []
self.max_length = max_length

def add_var(self, var):
self.lst += [var]


# Interface
def new_command(name, nl_length, pl_length, module, group, link, mad_8):
return None


def delete_command(command):
return None


def clone_command(command):
return None


def clone_command_flat(command):
return None


def find_command(name, command_list):
return None


# List Commands
def new_command_list(name, max_length):
return CommandList(name, max_length)


def delete_command_list(command_list):
return None


def find_command_list(name, command_list_list):
return None


def grow_command_list(command_list):
return None


def add_to_command_list(label, command, command_list, flag):
return None


def new_command_list_list(max_length):
return CommandListList(max_length)


def add_to_command_list_list(label, command_list, command_list_list):
return None


# Command Methods
def exec_command():
return None


def decode_command():
return None


def dump_command(command): # For Debugging
return None


def print_command(command):
return None


def store_command_def(): # Processes command definition
return None


def make_line(statement):
return None


def get_stmt(file, supp_flag):
return None


def get_defined_commands():
return None


def remove_from_command_list(label, command_list):
return None


def exec_add_expression(in_cmd):
return None
Loading