import json, sys from six import string_types header_template = """ [ ] """ # Each entry in the list is a chunk (probably a line) in the to-be-generated code high_level_interface = [ "", { "type": "print", "arguments": [ "'**************** INFORMATION ***************'" ], "EOL":True }, { "type": "print", "arguments": [ "'This example was auto-generated by the language-agnostic dev/scripts/example_generator.py script written by Ian Bell'" ], "EOL":True }, { "type": "print", "arguments": [ "'CoolProp version:'", { "type": "function", "function": "get_global_param_string", "arguments": [ "'version'" ] } ], "EOL":True }, { "type": "print", "arguments": [ "'CoolProp gitrevision:'", { "type": "function", "function": "get_global_param_string", "arguments": [ "'gitrevision'" ] } ], "EOL":True }, { "type": "print", "arguments": [ "'CoolProp Fluids:'", { "type": "function", "function": "get_global_param_string", "arguments": [ "'FluidsList'" ] } ], "EOL":True }, "", { "type": "comment", "comment": "See http://www.coolprop.org/coolprop/HighLevelAPI.html#table-of-string-inputs-to-propssi-function for a list of inputs to high-level interface", "EOL": True }, { "type": "print", "arguments": [ "'*********** HIGH LEVEL INTERFACE *****************'" ], "EOL":True }, { "type": "print", "arguments": [ "'Critical temperature of water:'", { "type": "function", "function": "Props1SI", "arguments": [ "'Water'", "'Tcrit'" ] }, "'K'" ], "EOL":True }, { "type": "print", "arguments": [ "'Boiling temperature of water at 101325 Pa:'", { "type": "function", "function": "PropsSI", "arguments": [ "'T'", "'P'", "101325", "'Q'", "0", "'Water'" ] }, "'K'" ], "EOL":True }, { "type": "print", "arguments": [ "'Phase of water at 101325 Pa and 300 K:'", { "type": "function", "function": "PhaseSI", "arguments": [ "'P'", "101325", "'T'", "300", "'Water'" ] } ], "EOL":True }, { "type": "print", "arguments": [ "'c_p of water at 101325 Pa and 300 K:'", { "type": "function", "function": "PropsSI", "arguments": [ "'C'", "'P'", "101325", "'T'", "300", "'Water'" ] }, "'J/kg/K'" ], "EOL":True }, { "type": "print", "arguments": [ "'c_p of water (using derivatives) at 101325 Pa and 300 K:'", { "type": "function", "function": "PropsSI", "arguments": [ "'d(H)/d(T)|P'", "'P'", "101325", "'T'", "300", "'Water'" ] }, "'J/kg/K'" ], "EOL":True }, "", { "type": "print", "arguments": ["'*********** HUMID AIR PROPERTIES *****************'"], "EOL":True }, { "type": "print", "arguments": [ "'Humidity ratio of 50% rel. hum. air at 300 K, 101325 Pa:'", { "type": "function", "function": "HAPropsSI", "arguments": [ "'W'", "'T'", "300", "'P'", "101325", "'R'", "0.5" ] }, "'kg_w/kg_da'" ], "EOL":True }, { "type": "print", "arguments": [ "'Relative humidity from last calculation:'", { "type": "function", "function": "HAPropsSI", "arguments": [ "'R'", "'T'", "300", "'P'", "101325", "'W'", { "type": "function", "function": "HAPropsSI", "arguments": [ "'W'", "'T'", "300", "'P'", "101325", "'R'", "0.5" ] } ] }, "'(fractional)'" ], "EOL":True }, "", { "type": "print", "arguments": ["'*********** INCOMPRESSIBLE FLUID AND BRINES *****************'"], "EOL":True }, { "type": "print", "arguments": [ "'Density of 50% (mass) ethylene glycol/water at 300 K, 101325 Pa:'", { "type": "function", "function": "PropsSI", "arguments": [ "'D'", "'T'", "300", "'P'", "101325", "'INCOMP::MEG-50%'" ] }, "'kg/m^3'" ], "EOL":True }, { "type": "print", "arguments": [ "'Viscosity of Therminol D12 at 350 K, 101325 Pa:'", { "type": "function", "function": "PropsSI", "arguments": [ "'V'", "'T'", "350", "'P'", "101325", "'INCOMP::TD12'" ] }, "'Pa-s'" ], "EOL":True }, "", { "type": "comment", "comment": "If you don't have REFPROP installed, disable the following lines", "EOL": True }, { "type": "print", "arguments": ["'*********** REFPROP *****************'"], "EOL":True }, { "type": "print", "arguments": [ "'REFPROP version:'", { "type": "function", "function": "get_global_param_string", "arguments": [ "'REFPROP_version'" ] } ], "EOL":True }, { "type": "print", "arguments": [ "'Critical temperature of water:'", { "type": "function", "function": "Props1SI", "arguments": [ "'REFPROP::WATER'", "'Tcrit'" ] }, "'K'" ], "EOL":True }, { "type": "print", "arguments": [ "'Boiling temperature of water at 101325 Pa:'", { "type": "function", "function": "PropsSI", "arguments": [ "'T'", "'P'", "101325", "'Q'", "0", "'REFPROP::WATER'" ] }, "'K'" ], "EOL":True }, { "type": "print", "arguments": [ "'c_p of water at 101325 Pa and 300 K:'", { "type": "function", "function": "PropsSI", "arguments": [ "'C'", "'P'", "101325", "'T'", "300", "'REFPROP::WATER'" ] }, "'J/kg/K'" ], "EOL":True } ] low_level_interface_with_mixtures = [ "", { "type": "print", "arguments": ["'*********** LOW-LEVEL INTERFACE *****************'"], "EOL":True }, { "type": "custom_assignment", "variable_type": "AbstractState", "variable_name": "AS", "RHS": { "type": "function", "function": "factory", "arguments": [ "'HEOS'", "'Water&Ethanol'" ] }, "EOL":True }, { "type": "custom_assignment", "variable_name": "z", "variable_type": "vector", "RHS": { "type": "vector", "arguments": [ "0.5", "0.5" ] }, "EOL":True }, { "type": "class_dereference", "name": "AS", "RHS": { "type": "function", "function": "set_mole_fractions", "arguments": [ "z" ] }, "EOL":True }, { "type": "class_dereference", "name": "AS", "RHS": { "type": "function", "function": "update", "arguments": [ { "type": "enum", "enum": "input_pairs", "key": "PQ_INPUTS" }, "101325", "1" ] }, "EOL": True }, { "type": "print", "arguments": [ "'Normal boiling point temperature of water and ethanol:'", { "type": "class_dereference", "name": "AS", "RHS": { "type": "function", "function": "T", "arguments": [] } }, "'K'" ], "EOL":True }, "", { "type": "comment", "comment": "If you don't have REFPROP installed, disable the following block", "EOL": True }, { "type": "print", "arguments": ["'*********** LOW-LEVEL INTERFACE (REFPROP) *****************'"], "EOL":True }, { "type": "custom_assignment", "variable_type": "AbstractState", "variable_name": "AS2", "RHS": { "type": "function", "function": "factory", "arguments": [ "'REFPROP'", "'METHANEÐANE'" ] }, "EOL":True }, { "type": "custom_assignment", "variable_name": "z2", "variable_type": "vector", "RHS": { "type": "vector", "arguments": [ "0.2", "0.8" ] }, "EOL":True }, { "type": "class_dereference", "name": "AS2", "RHS": { "type": "function", "function": "set_mole_fractions", "arguments": [ "z2" ] }, "EOL":True }, { "type": "class_dereference", "name": "AS2", "RHS": { "type": "function", "function": "update", "arguments": [ { "type": "enum", "enum": "input_pairs", "key": "QT_INPUTS" }, "1", "120" ] }, "EOL": True }, { "type": "print", "arguments": [ "'Vapor molar density:'", { "type": "class_dereference", "name": "AS2", "RHS": { "type": "function", "function": "keyed_output", "arguments": [ { "type": "enum", "enum": "parameters", "key": "iDmolar" } ] } }, "'mol/m^3'" ], "EOL": True } ] low_level_interface = [ "", { "type": "print", "arguments": ["'*********** TABULAR BACKENDS *****************'"], "EOL":True }, { "type": "custom_assignment", "variable_type": "AbstractState", "variable_name": "TAB", "RHS": { "type": "function", "function": "factory", "arguments": [ "'BICUBIC&HEOS'", "'R245fa'" ] }, "EOL":True }, { "type": "class_dereference", "name": "TAB", "RHS": { "type": "function", "function": "update", "arguments": [ { "type": "enum", "enum": "input_pairs", "key": "PT_INPUTS" }, "101325", "300" ] }, "EOL": True }, { "type": "print", "arguments": [ "'Mass density of refrigerant R245fa at 300 K, 101325 Pa:'", { "type": "class_dereference", "name": "TAB", "RHS": { "type": "function", "function": "rhomass", "arguments": [] } }, "'kg/m^3'" ], "EOL":True }, { "type": "print", "arguments": ["'*********** SATURATION DERIVATIVES (LOW-LEVEL INTERFACE) ***************'"], "EOL":True }, { "type": "custom_assignment", "variable_type": "AbstractState", "variable_name": "AS_SAT", "RHS": { "type": "function", "function": "factory", "arguments": [ "'HEOS'", "'R245fa'" ] }, "EOL":True }, { "type": "class_dereference", "name": "AS_SAT", "RHS": { "type": "function", "function": "update", "arguments": [ { "type": "enum", "enum": "input_pairs", "key": "PQ_INPUTS" }, "101325", "0" ] }, "EOL": True }, { "type": "print", "arguments": [ "'First saturation derivative:'", { "type": "class_dereference", "name": "AS_SAT", "RHS": { "type": "function", "function": "first_saturation_deriv", "arguments": [ { "type": "enum", "enum": "parameters", "key": "iP" }, { "type": "enum", "enum": "parameters", "key": "iT" } ] } }, "'Pa/K'" ], "EOL": True } ] class BaseParser(object): def __init__(self): self.pieces = high_level_interface + low_level_interface + low_level_interface_with_mixtures def footer(self): return '' def parse(self): lines = [] for line in self.pieces: if isinstance(line, string_types): lines.append(line) elif isinstance(line, dict): lines.append(self.dict2string(line)) else: raise ValueError() return ''.join(self.header()) + '\n'.join([self.indentation + line for line in lines if line]) + ''.join(self.footer()) def write(self, fname, code): with open(fname, 'w') as fp: fp.write(code) def map_function(self, name): if name in self.function_name_mapping: return self.function_name_mapping[name] else: return name class Python(BaseParser): function_name_mapping = dict(Props1SI='PropsSI', factory='AbstractState') type_name_mapping = {'vector': None, 'AbstractState': None} enum_name_mapping = {'input_pairs': "CoolProp", 'parameters': "CoolProp"} indentation = '' def parse_arguments(self, arguments): out = [] for arg in arguments: if isinstance(arg, string_types) and arg[0] == "'" and arg[-1] == "'": out.append('\"' + arg[1:-1] + '\"') elif isinstance(arg, dict): out.append(self.dict2string(arg)) else: out.append(arg) return out def dict2string(self, d): if d['type'] == 'comment': return '# ' + d['comment'] elif d['type'] == 'function': return self.map_function(d['function']) + '(' + ', '.join(self.parse_arguments(d['arguments'])) + ')' elif d['type'] == 'print': return 'print(' + ', '.join(self.parse_arguments(d['arguments'])) + ')' elif d['type'] == 'vector': return '[' + ', '.join(self.parse_arguments(d['arguments'])) + ']' elif d['type'] == 'enum': return self.enum_name_mapping[d['enum']] + '.' + d['key'] elif d['type'] == 'class_dereference': return d['name'] + '.' + self.dict2string(d['RHS']) elif d['type'] == 'custom_assignment': type_name = self.type_name_mapping[d['variable_type']] if type_name: LHS = type_name + ' ' + d['variable_name'] else: LHS = d['variable_name'] return ' '.join([LHS, '=', self.dict2string(d['RHS'])]) else: return '??????????????????????????????' def header(self): return '\n'.join(['from __future__ import print_function', 'from CoolProp import AbstractState', 'from CoolProp.CoolProp import PhaseSI, PropsSI, get_global_param_string', 'import CoolProp.CoolProp as CoolProp', 'from CoolProp.HumidAirProp import HAPropsSI', 'from math import sin\n']) class Octave(BaseParser): function_name_mapping = dict(Props1SI='CoolProp.Props1SI', PropsSI='CoolProp.PropsSI', PhaseSI='CoolProp.PhaseSI', HAPropsSI='CoolProp.HAPropsSI', get_global_param_string='CoolProp.get_global_param_string', factory='AbstractState.factory') type_name_mapping = {'vector': None, 'AbstractState': None} enum_name_mapping = {'input_pairs': "CoolProp", 'parameters': "CoolProp"} indentation = ' ' * 0 def parse_arguments(self, arguments): out = [] for arg in arguments: if isinstance(arg, string_types) and arg[0] == "'" and arg[-1] == "'": out.append('\'' + arg[1:-1] + '\'') elif isinstance(arg, dict): out.append(self.dict2string(arg)) else: out.append(arg) return out def dict2string(self, d): if d['type'] == 'comment': l = '% ' + d['comment'] elif d['type'] == 'function': l = self.map_function(d['function']) + '(' + ', '.join(self.parse_arguments(d['arguments'])) + ')' elif d['type'] == 'print': args = self.parse_arguments(d['arguments']) args = ['num2str(' + arg + ')' for arg in args] l = 'disp([' + ', \' \', '.join(args) + '])' elif d['type'] == 'vector': args = self.parse_arguments(d['arguments']) l = '[' + ', '.join(args) + ']' elif d['type'] == 'class_dereference': l = d['name'] + '.' + self.dict2string(d['RHS']) elif d['type'] == 'enum': l = self.enum_name_mapping[d['enum']] + '.' + d['key'] elif d['type'] == 'custom_assignment': type_name = self.type_name_mapping[d['variable_type']] if type_name: LHS = type_name + ' ' + d['variable_name'] else: LHS = d['variable_name'] if d['RHS']['type'] != 'vector': RHS = self.dict2string(d['RHS']) else: # Custom processing for vector assignment pushes = [d['variable_name'] + '.push_back(' + arg + ');' for arg in d['RHS']['arguments']] RHS = 'DoubleVector(); ' + ' '.join(pushes) l = ' '.join([LHS, '=', RHS]) else: l = '??????????????????????????????' if 'EOL' in d and d['EOL']: l += ';' return l def header(self): return '\n'.join(['CoolProp\n']) class R(BaseParser): function_name_mapping = dict(factory='AbstractState_factory') type_name_mapping = {'vector': None, 'AbstractState': None} enum_name_mapping = {'input_pairs': "CoolProp", 'parameters': "CoolProp"} indentation = ' ' * 0 def parse_arguments(self, arguments): out = [] for arg in arguments: if isinstance(arg, string_types) and arg[0] == "'" and arg[-1] == "'": out.append('\'' + arg[1:-1] + '\'') elif isinstance(arg, dict): out.append(self.dict2string(arg)) else: out.append(arg) return out def dict2string(self, d): if d['type'] == 'comment': l = '# ' + d['comment'] elif d['type'] == 'function': l = self.map_function(d['function']) + '(' + ', '.join(self.parse_arguments(d['arguments'])) + ')' elif d['type'] == 'print': args = self.parse_arguments(d['arguments']) l = 'writeLines(paste(' + ', \' \', '.join(args) + '))' elif d['type'] == 'vector': args = self.parse_arguments(d['arguments']) l = '[' + ', '.join(args) + ']' elif d['type'] == 'class_dereference': l = d['name'] + '$' + self.dict2string(d['RHS']) elif d['type'] == 'enum': l = '"' + d['key'] + '"' elif d['type'] == 'custom_assignment': type_name = self.type_name_mapping[d['variable_type']] if type_name: LHS = type_name + ' ' + d['variable_name'] else: LHS = d['variable_name'] if d['RHS']['type'] != 'vector': RHS = self.dict2string(d['RHS']) else: # Custom processing for vector assignment pushes = [d['variable_name'] + ' <- ' + arg + ';' for arg in d['RHS']['arguments']] RHS = 'c(' + ', '.join([arg for arg in d['RHS']['arguments']]) + ')' l = ' '.join([LHS, '=', RHS]) else: l = '??????????????????????????????' if 'EOL' in d and d['EOL']: l += '' return l def header(self): return 'dyn.load(paste("CoolProp", .Platform$dynlib.ext, sep=""))\nlibrary(methods) # See http://stackoverflow.com/a/19468533\nsource("CoolProp.R")\ncacheMetaData(1)\n' class MATLAB(BaseParser): function_name_mapping = dict(Props1SI='CoolProp.Props1SI', PropsSI='CoolProp.PropsSI', PhaseSI='CoolProp.PhaseSI', HAPropsSI='CoolProp.HAPropsSI', get_global_param_string='CoolProp.get_global_param_string', factory='CoolProp.AbstractState.factory') enum_name_mapping = {'input_pairs': "CoolProp", 'parameters': "CoolProp"} type_name_mapping = {'vector': None, 'AbstractState': None} indentation = '' def parse_arguments(self, arguments): out = [] for arg in arguments: if isinstance(arg, string_types) and arg[0] == "'" and arg[-1] == "'": out.append('\'' + arg[1:-1] + '\'') elif isinstance(arg, dict): out.append(self.dict2string(arg)) else: out.append(arg) return out def dict2string(self, d): if d['type'] == 'comment': l = '% ' + d['comment'] elif d['type'] == 'function': l = self.map_function(d['function']) + '(' + ', '.join(self.parse_arguments(d['arguments'])) + ')' elif d['type'] == 'print': args = self.parse_arguments(d['arguments']) args = ['num2str(' + arg + ')' for arg in args] l = 'disp([' + ', \' \', '.join(args) + '])' elif d['type'] == 'vector': args = self.parse_arguments(d['arguments']) l = '[' + ', '.join(args) + ']' elif d['type'] == 'enum': l = self.enum_name_mapping[d['enum']] + '.' + d['key'] elif d['type'] == 'class_dereference': l = d['name'] + '.' + self.dict2string(d['RHS']) elif d['type'] == 'custom_assignment': type_name = self.type_name_mapping[d['variable_type']] if type_name: LHS = type_name + ' ' + d['variable_name'] else: LHS = d['variable_name'] # Custom processing for vector assignment if d['RHS']['type'] != 'vector': RHS = self.dict2string(d['RHS']) else: # vector pushes = [d['variable_name'] + '.push_back(' + arg + ');' for arg in d['RHS']['arguments']] RHS = 'CoolProp.DoubleVector(); ' + ' '.join(pushes) l = ' '.join([LHS, '=', RHS]) else: l = '??????????????????????????????' if 'EOL' in d and d['EOL']: l += ';' return l def header(self): return '' class Java(BaseParser): function_name_mapping = dict(Props1SI='CoolProp.Props1SI', PropsSI='CoolProp.PropsSI', PhaseSI='CoolProp.PhaseSI', HAPropsSI='CoolProp.HAPropsSI', get_global_param_string='CoolProp.get_global_param_string', factory='AbstractState.factory') type_name_mapping = {'vector': 'DoubleVector', 'AbstractState': 'AbstractState'} enum_name_mapping = {'input_pairs': "input_pairs", 'parameters': "parameters"} indentation = ' ' * 8 def parse_arguments(self, arguments): out = [] for arg in arguments: if isinstance(arg, string_types) and arg[0] == "'" and arg[-1] == "'": out.append('\"' + arg[1:-1] + '\"') elif isinstance(arg, dict): out.append(self.dict2string(arg)) else: out.append(arg) return out def dict2string(self, d): if d['type'] == 'comment': l = '// ' + d['comment'] elif d['type'] == 'print': l = 'System.out.println(' + ' + " " + '.join(self.parse_arguments(d['arguments'])) + ')' elif d['type'] == 'function': l = self.map_function(d['function']) + '(' + ', '.join(self.parse_arguments(d['arguments'])) + ')' elif d['type'] == 'vector': l = '{' + ', '.join(self.parse_arguments(d['arguments'])) + '}' elif d['type'] == 'enum': l = self.enum_name_mapping[d['enum']] + '.' + d['key'] elif d['type'] == 'class_dereference': l = d['name'] + '.' + self.dict2string(d['RHS']) elif d['type'] == 'custom_assignment': type_name = self.type_name_mapping[d['variable_type']] if type_name: LHS = type_name + ' ' + d['variable_name'] else: LHS = d['variable_name'] if d['RHS']['type'] != 'vector': RHS = self.dict2string(d['RHS']) else: # Custom processing for vector assignment pushes = [d['variable_name'] + '.add(' + arg + ');' for arg in d['RHS']['arguments']] RHS = 'new DoubleVector(); ' + ' '.join(pushes) l = ' '.join([LHS, '=', RHS]) else: raise ValueError if 'EOL' in d and d['EOL']: l += ';' return l def header(self): return 'public class Example {\n static {\n System.loadLibrary("CoolProp");\n }\n\n public static void main(String argv[]){\n' def footer(self): return '\n }\n}' class Csharp(BaseParser): function_name_mapping = dict(Props1SI='CoolProp.Props1SI', PropsSI='CoolProp.PropsSI', PhaseSI='CoolProp.PhaseSI', HAPropsSI='CoolProp.HAPropsSI', get_global_param_string='CoolProp.get_global_param_string', factory='AbstractState.factory') type_name_mapping = {'vector': "DoubleVector", 'AbstractState': 'AbstractState'} enum_name_mapping = {'input_pairs': "input_pairs", 'parameters': "parameters"} indentation = ' ' * 12 def parse_arguments(self, arguments): out = [] for arg in arguments: if isinstance(arg, string_types) and arg[0] == "'" and arg[-1] == "'": out.append('\"' + arg[1:-1] + '\"') elif isinstance(arg, dict): out.append(self.dict2string(arg)) else: out.append(arg) return out def dict2string(self, d): if d['type'] == 'comment': l = '// ' + d['comment'] elif d['type'] == 'print': l = 'Console.Write(' + ' + " " + '.join(self.parse_arguments(d['arguments'])) + ' + "\\n")' elif d['type'] == 'function': l = self.map_function(d['function']) + '(' + ', '.join(self.parse_arguments(d['arguments'])) + ')' elif d['type'] == 'vector': l = 'new DoubleVector(new double[]{' + ', '.join(self.parse_arguments(d['arguments'])) + '})' elif d['type'] == 'enum': l = self.enum_name_mapping[d['enum']] + '.' + d['key'] elif d['type'] == 'class_dereference': l = d['name'] + '.' + self.dict2string(d['RHS']) elif d['type'] == 'custom_assignment': type_name = self.type_name_mapping[d['variable_type']] if type_name: LHS = type_name + ' ' + d['variable_name'] else: LHS = d['variable_name'] l = ' '.join([LHS, '=', self.dict2string(d['RHS'])]) else: raise ValueError if 'EOL' in d and d['EOL']: l += ';' return l def header(self): return 'using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace ConsoleApplication1\n{\n class Program\n {\n static void Main(string[] args)\n {\n' def footer(self): return '\n }\n }\n}' if __name__ == '__main__': import argparse parser = argparse.ArgumentParser() parser.add_argument("language", help="The target language (Python, Java, Csharp, etc.)") parser.add_argument("destination", help="The path to the output file") args = parser.parse_args() writer = locals()[args.language]() writer.write(args.destination, writer.parse()) print("written to %s" % args.destination)