Removing the printing part from javap. The bck2brwsr VM can now be compiled into JavaScript
1.1 --- a/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Fri Nov 16 08:12:01 2012 +0100
1.2 +++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Fri Nov 16 08:26:55 2012 +0100
1.3 @@ -2228,29 +2228,10 @@
1.4 function java_lang_String_toStringLjava_lang_String(arg0) {
1.5 return arg0.toString();
1.6 }
1.7 +function java_lang_String_toCharArrayAC(arg0) {
1.8 + return arg0.toString().split('');
1.9 +}
1.10 /*
1.11 -function java_lang_String_toCharArrayAC(arg0) {
1.12 - var arg1;
1.13 - var arg2;
1.14 -;
1.15 - var stack = new Array(5);
1.16 - var gt = 0;
1.17 - for(;;) switch(gt) {
1.18 - case 0: stack.push(arg0); // 42
1.19 - case 1: stack.push(stack.pop().count); // 180 1 97
1.20 - case 4: stack.push(new Array(stack.pop())); // 188 5
1.21 - case 6: arg1 = stack.pop(); // 76
1.22 - case 7: stack.push(arg0); // 42
1.23 - case 8: stack.push(0); // 3
1.24 - case 9: stack.push(arg0); // 42
1.25 - case 10: stack.push(stack.pop().count); // 180 1 97
1.26 - case 13: stack.push(arg1); // 43
1.27 - case 14: stack.push(0); // 3
1.28 - case 15: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138
1.29 - case 18: stack.push(arg1); // 43
1.30 - case 19: return stack.pop(); // 176
1.31 - }
1.32 -}
1.33 function java_lang_String_formatLjava_lang_StringLjava_lang_StringLjava_lang_Object(arg0,arg1) {
1.34 var stack = new Array();
1.35 var gt = 0;
1.36 @@ -2475,6 +2456,7 @@
1.37 String.prototype.substringLjava_lang_StringI = java_lang_String_substringLjava_lang_StringI;
1.38 String.prototype.substringLjava_lang_StringII = java_lang_String_substringLjava_lang_StringII;
1.39 String.prototype.equalsZLjava_lang_Object = java_lang_String_equalsZLjava_lang_Object;
1.40 +String.prototype.toCharArrayAC = java_lang_String_toCharArrayAC;
1.41 String.prototype.$instOf_java_lang_String = true;
1.42 String.prototype.$instOf_java_io_Serializable = true;
1.43 String.prototype.$instOf_java_lang_Comparable = true;
1.44 @@ -2532,7 +2514,6 @@
1.45 this.toUpperCaseLjava_lang_String = java_lang_String_toUpperCaseLjava_lang_String;
1.46 this.trimLjava_lang_String = java_lang_String_trimLjava_lang_String;
1.47 this.toStringLjava_lang_String = java_lang_String_toStringLjava_lang_String;
1.48 - this.toCharArrayAC = java_lang_String_toCharArrayAC;
1.49 this.internLjava_lang_String = java_lang_String_internLjava_lang_String;
1.50 this.compareToILjava_lang_Object = java_lang_String_compareToILjava_lang_Object;
1.51 */
2.1 --- a/javap/src/main/java/org/apidesign/javap/ClassData.java Fri Nov 16 08:12:01 2012 +0100
2.2 +++ b/javap/src/main/java/org/apidesign/javap/ClassData.java Fri Nov 16 08:26:55 2012 +0100
2.3 @@ -481,12 +481,6 @@
2.4 return this_class;
2.5 }
2.6
2.7 - public String TagString (int tag) {
2.8 - String res=Tables.tagName(tag);
2.9 - if (res==null) return "BOGUS_TAG:"+tag;
2.10 - return res;
2.11 - }
2.12 -
2.13 /**
2.14 * Returns string at that index.
2.15 */
2.16 @@ -654,19 +648,6 @@
2.17 return cpool_count;
2.18 }
2.19
2.20 - public String StringTag(int cpx) {
2.21 - byte tag=0;
2.22 - String str=null;
2.23 - try {
2.24 - if (cpx==0) throw new IndexOutOfBoundsException();
2.25 - tag=tags[cpx];
2.26 - return TagString(tag);
2.27 - } catch (IndexOutOfBoundsException e) {
2.28 - str="Incorrect CP index:"+cpx;
2.29 - }
2.30 - return str;
2.31 - }
2.32 -
2.33 /**
2.34 * Returns minor version of class file.
2.35 */
3.1 --- a/javap/src/main/java/org/apidesign/javap/Tables.java Fri Nov 16 08:12:01 2012 +0100
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,373 +0,0 @@
3.4 -/*
3.5 - * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
3.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3.7 - *
3.8 - * This code is free software; you can redistribute it and/or modify it
3.9 - * under the terms of the GNU General Public License version 2 only, as
3.10 - * published by the Free Software Foundation. Oracle designates this
3.11 - * particular file as subject to the "Classpath" exception as provided
3.12 - * by Oracle in the LICENSE file that accompanied this code.
3.13 - *
3.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
3.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3.17 - * version 2 for more details (a copy is included in the LICENSE file that
3.18 - * accompanied this code).
3.19 - *
3.20 - * You should have received a copy of the GNU General Public License version
3.21 - * 2 along with this work; if not, write to the Free Software Foundation,
3.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3.23 - *
3.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3.25 - * or visit www.oracle.com if you need additional information or have any
3.26 - * questions.
3.27 - */
3.28 -
3.29 -
3.30 -package org.apidesign.javap;
3.31 -
3.32 -
3.33 -
3.34 -public class Tables implements Constants {
3.35 - /**
3.36 - * Define mnemocodes table.
3.37 - */
3.38 - static Hashtable mnemocodes = new Hashtable(301, 0.5f);
3.39 - static String opcExtNamesTab[]=new String[128];
3.40 - static String opcPrivExtNamesTab[]=new String[128];
3.41 - static void defineNonPriv(int opc, String mnem) {
3.42 - mnemocodes.put(opcExtNamesTab[opc]=mnem, new Integer(opc_nonpriv*256+opc));
3.43 - }
3.44 - static void definePriv(int opc, String mnem) {
3.45 - mnemocodes.put(opcPrivExtNamesTab[opc]="priv_"+mnem, new Integer(opc_priv*256+opc));
3.46 - }
3.47 - static void defineExt(int opc, String mnem) {
3.48 - defineNonPriv(opc, mnem);
3.49 - definePriv(opc, mnem);
3.50 - }
3.51 - static { int k;
3.52 - for (k=0; k<opc_wide; k++) {
3.53 - mnemocodes.put(opcNamesTab[k], new Integer(k));
3.54 - }
3.55 - for (k=opc_wide+1; k<opcNamesTab.length; k++) {
3.56 - mnemocodes.put(opcNamesTab[k], new Integer(k));
3.57 - }
3.58 - mnemocodes.put("invokenonvirtual", new Integer(opc_invokespecial));
3.59 -
3.60 - mnemocodes.put("iload_w", new Integer(opc_iload_w));
3.61 - mnemocodes.put("lload_w", new Integer(opc_lload_w));
3.62 - mnemocodes.put("fload_w", new Integer(opc_fload_w));
3.63 - mnemocodes.put("dload_w", new Integer(opc_dload_w));
3.64 - mnemocodes.put("aload_w", new Integer(opc_aload_w));
3.65 - mnemocodes.put("istore_w", new Integer(opc_istore_w));
3.66 - mnemocodes.put("lstore_w", new Integer(opc_lstore_w));
3.67 - mnemocodes.put("fstore_w", new Integer(opc_fstore_w));
3.68 - mnemocodes.put("dstore_w", new Integer(opc_dstore_w));
3.69 - mnemocodes.put("astore_w", new Integer(opc_astore_w));
3.70 - mnemocodes.put("ret_w", new Integer(opc_ret_w));
3.71 - mnemocodes.put("iinc_w", new Integer(opc_iinc_w));
3.72 -
3.73 - mnemocodes.put("nonpriv", new Integer(opc_nonpriv));
3.74 - mnemocodes.put("priv", new Integer(opc_priv));
3.75 -
3.76 - defineExt(0, "load_ubyte");
3.77 - defineExt(1, "load_byte");
3.78 - defineExt(2, "load_char");
3.79 - defineExt(3, "load_short");
3.80 - defineExt(4, "load_word");
3.81 - defineExt(10, "load_char_oe");
3.82 - defineExt(11, "load_short_oe");
3.83 - defineExt(12, "load_word_oe");
3.84 - defineExt(16, "ncload_ubyte");
3.85 - defineExt(17, "ncload_byte");
3.86 - defineExt(18, "ncload_char");
3.87 - defineExt(19, "ncload_short");
3.88 - defineExt(20, "ncload_word");
3.89 - defineExt(26, "ncload_char_oe");
3.90 - defineExt(27, "ncload_short_oe");
3.91 - defineExt(28, "ncload_word_oe");
3.92 - defineExt(30, "cache_flush");
3.93 - defineExt(32, "store_byte");
3.94 - defineExt(34, "store_short");
3.95 - defineExt(36, "store_word");
3.96 - defineExt(42, "store_short_oe");
3.97 - defineExt(44, "store_word_oe");
3.98 - defineExt(48, "ncstore_byte");
3.99 - defineExt(50, "ncstore_short");
3.100 - defineExt(52, "ncstore_word");
3.101 - defineExt(58, "ncstore_short_oe");
3.102 - defineExt(60, "ncstore_word_oe");
3.103 - defineExt(62, "zero_line");
3.104 - defineNonPriv(5, "ret_from_sub");
3.105 - defineNonPriv(63, "enter_sync_method");
3.106 - definePriv(5, "ret_from_trap");
3.107 - definePriv(6, "read_dcache_tag");
3.108 - definePriv(7, "read_dcache_data");
3.109 - definePriv(14, "read_icache_tag");
3.110 - definePriv(15, "read_icache_data");
3.111 - definePriv(22, "powerdown");
3.112 - definePriv(23, "read_scache_data");
3.113 - definePriv(31, "cache_index_flush");
3.114 - definePriv(38, "write_dcache_tag");
3.115 - definePriv(39, "write_dcache_data");
3.116 - definePriv(46, "write_icache_tag");
3.117 - definePriv(47, "write_icache_data");
3.118 - definePriv(54, "reset");
3.119 - definePriv(55, "write_scache_data");
3.120 - for (k=0; k<32; k++) {
3.121 - definePriv(k+64, "read_reg_"+k);
3.122 - }
3.123 - for (k=0; k<32; k++) {
3.124 - definePriv(k+96, "write_reg_"+k);
3.125 - }
3.126 - }
3.127 -
3.128 - public static int opcLength(int opc) throws ArrayIndexOutOfBoundsException {
3.129 - switch (opc>>8) {
3.130 - case 0:
3.131 - return opcLengthsTab[opc];
3.132 - case opc_wide:
3.133 - switch (opc&0xFF) {
3.134 - case opc_aload: case opc_astore:
3.135 - case opc_fload: case opc_fstore:
3.136 - case opc_iload: case opc_istore:
3.137 - case opc_lload: case opc_lstore:
3.138 - case opc_dload: case opc_dstore:
3.139 - case opc_ret:
3.140 - return 4;
3.141 - case opc_iinc:
3.142 - return 6;
3.143 - default:
3.144 - throw new ArrayIndexOutOfBoundsException();
3.145 - }
3.146 - case opc_nonpriv:
3.147 - case opc_priv:
3.148 - return 2;
3.149 - default:
3.150 - throw new ArrayIndexOutOfBoundsException();
3.151 - }
3.152 - }
3.153 -
3.154 - public static String opcName(int opc) {
3.155 - try {
3.156 - switch (opc>>8) {
3.157 - case 0:
3.158 - return opcNamesTab[opc];
3.159 - case opc_wide: {
3.160 - String mnem=opcNamesTab[opc&0xFF]+"_w";
3.161 - if (mnemocodes.get(mnem) == null)
3.162 - return null; // non-existent opcode
3.163 - return mnem;
3.164 - }
3.165 - case opc_nonpriv:
3.166 - return opcExtNamesTab[opc&0xFF];
3.167 - case opc_priv:
3.168 - return opcPrivExtNamesTab[opc&0xFF];
3.169 - default:
3.170 - return null;
3.171 - }
3.172 - } catch (ArrayIndexOutOfBoundsException e) {
3.173 - switch (opc) {
3.174 - case opc_nonpriv:
3.175 - return "nonpriv";
3.176 - case opc_priv:
3.177 - return "priv";
3.178 - default:
3.179 - return null;
3.180 - }
3.181 - }
3.182 - }
3.183 -
3.184 - public static int opcode(String mnem) {
3.185 - Integer Val=(Integer)(mnemocodes.get(mnem));
3.186 - if (Val == null) return -1;
3.187 - return Val.intValue();
3.188 - }
3.189 -
3.190 - /**
3.191 - * Initialized keyword and token Hashtables
3.192 - */
3.193 - static Vector keywordNames = new Vector(40);
3.194 - private static void defineKeywordName(String id, int token) {
3.195 -
3.196 - if (token>=keywordNames.size()) {
3.197 - keywordNames.setSize(token+1);
3.198 - }
3.199 - keywordNames.setElementAt(id, token);
3.200 - }
3.201 - public static String keywordName(int token) {
3.202 - if (token==-1) return "EOF";
3.203 - if (token>=keywordNames.size()) return null;
3.204 - return (String)keywordNames.elementAt(token);
3.205 - }
3.206 - static {
3.207 - defineKeywordName("ident", IDENT);
3.208 - defineKeywordName("STRINGVAL", STRINGVAL);
3.209 - defineKeywordName("intVal", INTVAL);
3.210 - defineKeywordName("longVal", LONGVAL);
3.211 - defineKeywordName("floatVal", FLOATVAL);
3.212 - defineKeywordName("doubleVal", DOUBLEVAL);
3.213 - defineKeywordName("SEMICOLON", SEMICOLON);
3.214 - defineKeywordName("COLON", COLON);
3.215 - defineKeywordName("LBRACE", LBRACE);
3.216 - defineKeywordName("RBRACE", RBRACE);
3.217 - }
3.218 -
3.219 - static Hashtable keywords = new Hashtable(40);
3.220 - public static int keyword(String idValue) {
3.221 - Integer Val=(Integer)(keywords.get(idValue));
3.222 - if (Val == null) return IDENT;
3.223 - return Val.intValue();
3.224 - }
3.225 -
3.226 - private static void defineKeyword(String id, int token) {
3.227 - keywords.put(id, new Integer(token));
3.228 - defineKeywordName(id, token);
3.229 - }
3.230 - static {
3.231 - // Modifier keywords
3.232 - defineKeyword("private", PRIVATE);
3.233 - defineKeyword("public", PUBLIC);
3.234 - defineKeyword("protected", PROTECTED);
3.235 - defineKeyword("static", STATIC);
3.236 - defineKeyword("transient", TRANSIENT);
3.237 - defineKeyword("synchronized", SYNCHRONIZED);
3.238 - defineKeyword("super", SUPER);
3.239 - defineKeyword("native", NATIVE);
3.240 - defineKeyword("abstract", ABSTRACT);
3.241 - defineKeyword("volatile", VOLATILE);
3.242 - defineKeyword("final", FINAL);
3.243 - defineKeyword("interface",INTERFACE);
3.244 - defineKeyword("synthetic",SYNTHETIC);
3.245 - defineKeyword("strict",STRICT);
3.246 -
3.247 - // Declaration keywords
3.248 - defineKeyword("package",PACKAGE);
3.249 - defineKeyword("class",CLASS);
3.250 - defineKeyword("extends",EXTENDS);
3.251 - defineKeyword("implements",IMPLEMENTS);
3.252 - defineKeyword("const", CONST);
3.253 - defineKeyword("throws",THROWS);
3.254 - defineKeyword("interface",INTERFACE);
3.255 - defineKeyword("Method",METHODREF);
3.256 - defineKeyword("Field",FIELDREF);
3.257 - defineKeyword("stack",STACK);
3.258 - defineKeyword("locals",LOCAL);
3.259 -
3.260 - // used in switchtables
3.261 - defineKeyword("default", DEFAULT);
3.262 -
3.263 - // used in inner class declarations
3.264 - defineKeyword("InnerClass", INNERCLASS);
3.265 - defineKeyword("of", OF);
3.266 -
3.267 - // misc
3.268 - defineKeyword("bits",BITS);
3.269 - defineKeyword("Infinity",INF);
3.270 - defineKeyword("Inf",INF);
3.271 - defineKeyword("NaN",NAN);
3.272 - }
3.273 -
3.274 - /**
3.275 - * Define tag table.
3.276 - */
3.277 - private static Vector tagNames = new Vector(10);
3.278 - private static Hashtable Tags = new Hashtable(10);
3.279 - static {
3.280 - defineTag("Asciz",CONSTANT_UTF8);
3.281 - defineTag("int",CONSTANT_INTEGER);
3.282 - defineTag("float",CONSTANT_FLOAT);
3.283 - defineTag("long",CONSTANT_LONG);
3.284 - defineTag("double",CONSTANT_DOUBLE);
3.285 - defineTag("class",CONSTANT_CLASS);
3.286 - defineTag("String",CONSTANT_STRING);
3.287 - defineTag("Field",CONSTANT_FIELD);
3.288 - defineTag("Method",CONSTANT_METHOD);
3.289 - defineTag("InterfaceMethod",CONSTANT_INTERFACEMETHOD);
3.290 - defineTag("NameAndType",CONSTANT_NAMEANDTYPE);
3.291 - }
3.292 - private static void defineTag(String id, int val) {
3.293 - Tags.put(id, new Integer(val));
3.294 - if (val>=tagNames.size()) {
3.295 - tagNames.setSize(val+1);
3.296 - }
3.297 - tagNames.setElementAt(id, val);
3.298 - }
3.299 - public static String tagName(int tag) {
3.300 - if (tag>=tagNames.size()) return null;
3.301 - return (String)tagNames.elementAt(tag);
3.302 - }
3.303 - public static int tagValue(String idValue) {
3.304 - Integer Val=(Integer)(Tags.get(idValue));
3.305 - if (Val == null) return 0;
3.306 - return Val.intValue();
3.307 - }
3.308 -
3.309 - /**
3.310 - * Define type table. These types used in "newarray" instruction only.
3.311 - */
3.312 - private static Vector typeNames = new Vector(10);
3.313 - private static Hashtable Types = new Hashtable(10);
3.314 - static {
3.315 - defineType("int",T_INT);
3.316 - defineType("long",T_LONG);
3.317 - defineType("float",T_FLOAT);
3.318 - defineType("double",T_DOUBLE);
3.319 - defineType("class",T_CLASS);
3.320 - defineType("boolean",T_BOOLEAN);
3.321 - defineType("char",T_CHAR);
3.322 - defineType("byte",T_BYTE);
3.323 - defineType("short",T_SHORT);
3.324 - }
3.325 - private static void defineType(String id, int val) {
3.326 - Types.put(id, new Integer(val));
3.327 - if (val>=typeNames.size()) {
3.328 - typeNames.setSize(val+1);
3.329 - }
3.330 - typeNames.setElementAt(id, val);
3.331 - }
3.332 - public static int typeValue(String idValue) {
3.333 - Integer Val=(Integer)(Types.get(idValue));
3.334 - if (Val == null) return -1;
3.335 - return Val.intValue();
3.336 - }
3.337 - public static String typeName(int type) {
3.338 - if (type>=typeNames.size()) return null;
3.339 - return (String)typeNames.elementAt(type);
3.340 - }
3.341 -
3.342 - /**
3.343 - * Define MapTypes table.
3.344 - * These constants used in stackmap tables only.
3.345 - */
3.346 - private static Vector mapTypeNames = new Vector(10);
3.347 - private static Hashtable MapTypes = new Hashtable(10);
3.348 - static {
3.349 - defineMapType("bogus", ITEM_Bogus);
3.350 - defineMapType("int", ITEM_Integer);
3.351 - defineMapType("float", ITEM_Float);
3.352 - defineMapType("double", ITEM_Double);
3.353 - defineMapType("long", ITEM_Long);
3.354 - defineMapType("null", ITEM_Null);
3.355 - defineMapType("this", ITEM_InitObject);
3.356 - defineMapType("CP", ITEM_Object);
3.357 - defineMapType("uninitialized", ITEM_NewObject);
3.358 - }
3.359 - private static void defineMapType(String id, int val) {
3.360 - MapTypes.put(id, new Integer(val));
3.361 - if (val>=mapTypeNames.size()) {
3.362 - mapTypeNames.setSize(val+1);
3.363 - }
3.364 - mapTypeNames.setElementAt(id, val);
3.365 - }
3.366 - public static int mapTypeValue(String idValue) {
3.367 - Integer Val=(Integer)(MapTypes.get(idValue));
3.368 - if (Val == null) return -1;
3.369 - return Val.intValue();
3.370 - }
3.371 - public static String mapTypeName(int type) {
3.372 - if (type>=mapTypeNames.size()) return null;
3.373 - return (String)mapTypeNames.elementAt(type);
3.374 - }
3.375 -
3.376 -}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Fri Nov 16 08:26:55 2012 +0100
4.3 @@ -0,0 +1,55 @@
4.4 +/**
4.5 + * Back 2 Browser Bytecode Translator
4.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
4.7 + *
4.8 + * This program is free software: you can redistribute it and/or modify
4.9 + * it under the terms of the GNU General Public License as published by
4.10 + * the Free Software Foundation, version 2 of the License.
4.11 + *
4.12 + * This program is distributed in the hope that it will be useful,
4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.15 + * GNU General Public License for more details.
4.16 + *
4.17 + * You should have received a copy of the GNU General Public License
4.18 + * along with this program. Look for COPYING file in the top folder.
4.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
4.20 + */
4.21 +package org.apidesign.vm4brwsr;
4.22 +
4.23 +import static org.testng.Assert.*;
4.24 +import javax.script.Invocable;
4.25 +import org.testng.annotations.BeforeClass;
4.26 +import org.testng.annotations.Test;
4.27 +
4.28 +/**
4.29 + *
4.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
4.31 + */
4.32 +public class VMinVMTest {
4.33 +
4.34 + private static CharSequence codeSeq;
4.35 + private static Invocable code;
4.36 +
4.37 + @Test public void compareTheGeneratedCode() throws Exception {
4.38 + StringBuilder hotspot = new StringBuilder();
4.39 + GenJS.compile(hotspot, "org/apidesign/vm4brwsr/Array");
4.40 +
4.41 + Object ret = code.invokeFunction(
4.42 + "org_apidesign_vm4brwsr_GenJS_toStringLjava_lang_StringLjava_lang_String",
4.43 + "org/apidesign/vm4brwsr/Array"
4.44 + );
4.45 + assertTrue(ret instanceof String, "It is string: " + ret);
4.46 +
4.47 + assertEquals((String)ret, hotspot.toString(), "The code is the same");
4.48 + }
4.49 +
4.50 + @BeforeClass
4.51 + public void compileTheCode() throws Exception {
4.52 + StringBuilder sb = new StringBuilder();
4.53 + code = StaticMethodTest.compileClass(sb,
4.54 + "org/apidesign/vm4brwsr/GenJS"
4.55 + );
4.56 + codeSeq = sb;
4.57 + }
4.58 +}